Каковы (tf) секреты выделения памяти в PDF (CGPDFDocumentRef) - PullRequest
7 голосов
/ 12 января 2011

Для читателя PDF я хочу подготовить документ, сделав «скриншоты» каждой страницы и сохранив их на диск. Первый подход

CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL);
for (int i = 1; i<=pageCount; i++) 
{
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];      
  CGPDFPageRef page = CGPDFDocumentGetPage(document, i);
  ...//getting + manipulating graphics context etc.
  ...
  CGContextDrawPDFPage(context, page);
  ...
  UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
  ...//saving the image to disc 
  [pool drain];
}
CGPDFDocumentRelease(document);

Это приводит к большому количеству памяти, которая, похоже, не освобождается после первого запуска цикла (подготовка 1-го документа), но больше не освобождает память при дополнительных запусках:

MEMORY BEFORE:          6 MB
MEMORY DURING 1ST DOC: 40 MB
MEMORY AFTER 1ST  DOC: 25 MB 
MEMORY DURING 2ND DOC: 40 MB
MEMORY AFTER 2ND  DOC: 25 MB
....

Изменение кода на

for (int i = 1; i<=pageCount; i++) 
{
  CGPDFDocumentRef document = CGPDFDocumentCreateWithURL((CFURLRef) someURL);
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];      
  CGPDFPageRef page = CGPDFDocumentGetPage(document, i);
  ...//getting + manipulating graphics context etc.
  ...
  CGContextDrawPDFPage(context, page);
  ...
  UIImage *resultingImage = UIGraphicsGetImageFromCurrentImageContext();
  ...//saving the image to disc 
  CGPDFDocumentRelease(document);
  [pool drain];
}

изменяет использование памяти на

MEMORY BEFORE:          6 MB
MEMORY DURING 1ST DOC:  9 MB
MEMORY AFTER 1ST  DOC:  7 MB 
MEMORY DURING 2ND DOC:  9 MB
MEMORY AFTER 2ND  DOC:  7 MB
....

но, очевидно, это шаг назад по производительности.

Когда я начинаю читать PDF (позже, другой поток), в первом случае больше не выделяется память (оставаясь на уровне 25 МБ), тогда как во втором случае объем памяти увеличивается до 20 МБ (с 7).

В обоих случаях при удалении строки CGContextDrawPDFPage(context, page); память (почти) постоянна и составляет 6 МБ во время и после всех подготовок документов.

Кто-нибудь может объяснить, что там происходит?

1 Ответ

4 голосов
/ 13 января 2011

CGPDFDocument кеширует довольно агрессивно, и у вас очень мало контроля над этим, кроме - как вы уже сделали - выпуска документа и его перезагрузки с диска.

Причина, по которой вы не видите многоВыделение при удалении вызова CGContextDrawPDFPage заключается в том, что Quartz загружает ресурсы страницы лениво.Когда вы просто вызываете CGPDFDocumentGetPage, все, что происходит, это то, что он загружает некоторые базовые метаданные, такие как ограничивающие рамки и аннотации (очень маленькие в памяти).

Шрифты, изображения и т. Д. Загружаются только тогда, когда вы фактически рисуете страницу- но затем они довольно долго хранятся во внутреннем кэше.Это сделано для ускорения рендеринга, потому что ресурсы страницы часто распределяются между несколькими страницами.Кроме того, довольно часто визуализировать страницу несколько раз (например, при увеличении).Вы заметите, что визуализация страницы во второй раз выполняется значительно быстрее.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...