تحسين استهلاك الذاكرة عند الكتابة تدريجيا إلى ملف
-
27-09-2019 - |
سؤال
لقد قمت ببعض الاختبارات ، وأحد احتياجاتي هو قراءة البيانات من ملفات XML المختلفة وتكديسها معًا على ملف واحد. على الرغم من أنني تمكنت من تحقيق ذلك ، يبدو أن استهلاك الذاكرة كبير جدًا لهذه المهمة ، إلا أن جهاز iPhone Simulator لم يرفع تحذير الذاكرة ، لكنني لا أعتقد أن iPhone الحقيقي سوف يتسامح مع هذا (ليس لدي هذا جهاز لتجربته هنا ، لذلك أنا في الغالب أتحمل ذلك مما قرأته).
يشبه الجزء الرئيسي من الكود):
Boolean success = [fileManager createFileAtPath:documentsPath contents:nil attributes:nil];
[fileManager release];
if (success) {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForWritingAtPath:documentsPath];
for (int i = 0; i < 100; i++) {
NSString *path = [[NSBundle mainBundle] pathForResource:@"mensagem_de_arquivo"
ofType:@"xml"];
NSData *data = [NSData dataWithContentsOfFile:path];
GDataXMLDocument *xml = [[GDataXMLDocument alloc] initWithData:data options:0 error:nil];
NSArray *tokens = [xml nodesForXPath:@"//message/data" error:nil];
if (tokens.count > 0) {
GDataXMLElement *token = (GDataXMLElement *)[tokens objectAtIndex:0];
[fileHandle writeData:[[token stringValue] dataUsingEncoding:NSASCIIStringEncoding]];
}
[xml release];
}
لا يعطيني استخدام أمر "Build and Analyze" أي تسرب أو أي شيء ، ولا يرفع الرمز تحذيرات عند البناء ، ولكن لا يزال استهلاك الذاكرة يتراوح بين 50 و 70 ميجابايت (مجرد التفكير في البايتات الحية ، بشكل عام يتضاعف تقريبًا).
من الواضح أن الفكرة لا تقرأ 100 مرة من نفس الملف ، ولكن كاختبار بياناته أكثر من الكافيين ، يجب على الكود قراءة المحتويات من ملفات XML فقط وإرسالها إلى ملف بالترتيب الذي يتم استلامه.
هل هناك أي طريقة لإجبار بعض الأشياء المؤقتة قبل تخصيص الأشياء الجديدة ، هل يمكنني محاولة إعادة استخدام بعض المتغيرات ، أي أفكار تساعدني على الحفاظ على هذا تحت السيطرة.
يحرر - فقط لجعل الأمور أكثر إثارة للاهتمام: سيكون من الأفضل الحفاظ على محلل واحد للقراءة والكتابة ، ومن خلال ذلك الأفضل هو التمسك بـ gdataxml أو ، إذا كان هناك حاجة إلى تغيير ، لاستخدام KissXML libxml - DOM ، والتي يبدو أنها تمتص المزيد من الذاكرة ، كما قال هنا, ، لذلك إذا كانت هناك طريقة لفرض إصدار الذاكرة فسيكون ذلك هو الأفضل.
شكرا مقدما :)
المحلول
في الواقع ، لقد كان حلًا بسيطًا جدًا.
كل ما كان علي فعله هو إنشاء مثيل للسيارات وتصريفه في نهاية الحلقة.
مثله:
for (int i = 0; i < 100; i++) {
NSAutoReleasePool *pool = [[NSAutoReleasePool alloc] init];
//... do everything I've done before...
[pool drain];
}
أجبر هذا على إطلاق كائنات تم وضع علامة عليها على أنها تم تأسيسها داخل The For ، والتي تم إطلاقها للتو بعد نهاية الأمر ، كما كان متوقعًا ، دون التدخل في كل شيء آخر ، لذلك لم يتم إطلاق أي أشياء قبل ذلك.
انخفض استهلاك الذاكرة من 60 ميغابايت من 60 ميغابايت إلى شيء مثل 1،6 ميجابايت خلال الحلقة ، والعودة إلى نفس 600 كيلو بايت بعد ذلك (كان تطبيق وهمية القيام بذلك فقط).
ما زلت أترك هذا السؤال مفتوحًا لفترة من الوقت ، في حال كان لدى شخص ما فكرة أفضل ، ولكن في الوقت الحالي ، يبدو أن هذا سيكون الطريق :)
نصائح أخرى
نعم ، لقد "تضاعفت" من خلال قراءتها جميعًا في NSDATA ، ثم التحليل في DOM في GDATAXMLDOCUMITY. إذا كنت تتوقع أن تمر بالكثير من بيانات XML مثل هذا ، فالحلق على ملفات متعددة ، وما إلى ذلك ، فيجب عليك ذلك النظر في تحليل ساكس المستند إلى ساكس بدلاً من ذلك, ، وتدفقه مباشرة من الملف بدلاً من التحميل المسبق له في NSDATA. وبهذه الطريقة ، لن تضطر إلى "إصدار كائنات مؤقتة" لأنك ستستخرج فقط المعلومات التي تحتاجها ، حيث يتم تحليلها.