问题描述
对于PDF阅读器,我想通过获取每个页面的屏幕截图并将它们保存到光盘来准备文档。第一种方法是
For a PDF reader I want to prepare a document by taking 'screenshots' of each page and save them to disc. First approach is
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);
这会导致大量内存在首次运行循环后似乎无法释放(准备第一份文件),但在额外的运行中没有更多未发布的内存:
This results in a lot of memory which seems not to be released after the first run of the loop (preparing the 1st document), but no more unreleased memory in additional runs:
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
....
但是表现显然是倒退一步。
but is obviously a step backwards in performance.
当我在第一种情况下开始阅读PDF(稍后时间,不同的线程)时,不再分配更多内存(保持25 MB),而在第二种情况下内存最高可达20 MB(从7开始)。
When I start reading a PDF (later in time, different thread) in the first case no more memory is allocated (staying at 25 MB), while in the second case memory goes up to 20 MB (from 7).
在这两种情况下,当我删除 CGContextDrawPDFPage(上下文,页面);
行内存(几乎)不变在所有文件准备期间和之后都是6 MB。
In both cases, when I remove the CGContextDrawPDFPage(context, page);
line memory is (nearly) constant at 6 MB during and after all preparations of documents.
有人可以解释那里发生的事情吗?
Can anybody explain whats going on there?
推荐答案
CGPDFDocument非常积极地缓存,你几乎无法控制它,除了 - 正如你所做的那样 - 释放文件并从磁盘重新加载。
CGPDFDocument caches pretty aggressively and you have very little control over that, apart from - as you've done - releasing the document and reloading it from disk.
当您删除CGContextDrawPDFPage调用时没有看到大量分配的原因是Quartz懒惰地加载页面资源。当您只调用CGPDFDocumentGetPage时,所有发生的事情是它加载一些基本元数据,如边界框和注释(内存非常小)。
The reason you don't see a lot of allocations when you remove the CGContextDrawPDFPage call is that Quartz loads page resources lazily. When you just call CGPDFDocumentGetPage, all that happens is that it loads some basic metadata, like bounding boxes and annotations (very small in memory).
字体,图像等。只有在您实际绘制页面时才会加载 - 但是它们会在内部缓存中保留相对较长的时间。这意味着使渲染更快,因为页面资源通常在多个页面之间共享。此外,多次渲染页面(例如放大时)相当常见。您会注意到第二次呈现页面要快得多。
Fonts, images, etc. are only loaded when you actually draw the page - but then they're retained for a relatively long time in an internal cache. This is meant to make rendering faster, because page resources are often shared between multiple pages. Also, it's fairly common to render a page multiple times (e.g. when zooming in). You'll notice that it's significantly faster to render a page the second time.
这篇关于什么(tf)是PDF内存分配背后的秘密(CGPDFDocumentRef)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!