- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我的类(class)正在屏幕外渲染图像。我认为重用 CGContext
而不是一次又一次地为每个图像创建相同的上下文将是一件好事。我设置了一个成员变量 _imageContext
,所以如果 _imageContext
为 nil,我只需要创建一个新的上下文,如下所示:
if(!_imageContext)
_imageContext = [self contextOfSize:imageSize];
代替:
CGContextRef imageContext = [self contextOfSize:imageSize];
当然我不再发布CGContext
了。
这些是我所做的唯一更改,事实证明,重用上下文将渲染速度从大约 10 毫秒减慢到 60 毫秒。我错过了什么吗?在再次进入之前我是否必须清除上下文或其他内容?还是为每个图像重新创建上下文的正确方法?
编辑
找到最奇怪的联系..
当我在寻找当应用程序开始呈现图像时应用程序的内存显着增加的原因时,我发现问题出在我将呈现的图像设置为 NSImageView
。
imageView.image = nil;
imageView.image = [[NSImage alloc] initWithCGImage:_imageRef size:size];
看起来 ARC 没有发布之前的 NSImage
。避免这种情况的第一种方法是将新图像绘制到旧图像中。
[imageView.image lockFocus];
[[[NSImage alloc] initWithCGImage:_imageRef size:size] drawInRect:NSMakeRect(0, 0, size.width, size.height) fromRect:NSZeroRect operation:NSCompositeSourceOver fraction:1.0];
[imageView.image unlockFocus];
[imageView setNeedsDisplay];
内存问题消失了,CGContext
- 重用问题发生了什么?不重用上下文现在需要 20 毫秒而不是 10 毫秒 - 当然绘制到图像中比仅仅设置它需要更长的时间。重用上下文也需要 20 毫秒而不是 60 毫秒。但为什么?我看不出可能有任何联系,但我可以通过设置 NSImageView
的图像而不是绘制它来重现重复使用需要更多时间的旧状态。
最佳答案
我对此进行了调查,并观察到同样的减速。将 Instruments 设置为对内核调用和用户态调用进行采样显示了罪魁祸首。 @RyanArtecona 的评论是正确的。我在两次测试运行中将 Instruments 集中在最底部的用户区调用 CGSColorMaskCopyARGB8888_sse
(一次重用上下文,另一次每次都创建一个新上下文),然后反转生成的调用树。在不重用上下文的情况下,我看到最重的内核跟踪是:
Running Time Self Symbol Name
668.0ms 32.3% 668.0 __bzero
668.0ms 32.3% 0.0 vm_fault
668.0ms 32.3% 0.0 user_trap
668.0ms 32.3% 0.0 CGSColorMaskCopyARGB8888_sse
这是内核将因 CGSColorMaskCopyARGB8888_sse
访问而出现故障的内存页面归零。这意味着 CGContext 映射 VM 页面以支持位图上下文,但内核实际上并不执行与该操作相关的工作,直到有人实际访问该内存。实际映射/错误发生在第一次访问时。
现在让我们看看重用上下文时最重的内核跟踪:
Running Time Self Symbol Name
1327.0ms 35.0% 1327.0 bcopy
1327.0ms 35.0% 0.0 user_trap
1327.0ms 35.0% 0.0 CGSColorMaskCopyARGB8888_sse
这是内核复制页面。我的钱将用于提供@RyanArtecona 在他的评论中谈到的行为的底层写时复制机制:
In the Apple docs for CGBitmapContextCreateImage, it says the actual bit-copying operation doesn't happen until more drawing is done on the original context.
在我用来测试的设计案例中,非重用案例的执行时间为 3392 毫秒,而重用案例的执行时间为 4693 毫秒(明显较慢)。仅考虑每种情况下最重的单个跟踪,内核跟踪表明我们在第一次访问时花费了 668.0ms 零填充新页面,在图像获得引用后的第一次写入中花费了 1327.0ms 写入写时复制页面到那些页面。这是 659 毫秒的差异。仅这一差异就占了两种情况之间差距的约 50%。
因此,简单地提炼一下,非重用上下文更快,因为当您创建上下文时,它知道页面是空的,并且没有其他人引用这些页面来强制复制它们你写信给他们。当您重用上下文时,页面会被其他人(您创建的图像)引用,并且必须在第一次写入时复制,以便在上下文状态发生变化时保留图像的状态。
您可以在调试器中单步执行时通过查看进程的虚拟内存映射来进一步探索这里发生的事情。 vmmap
是一个有用的工具。
实际上,您应该每次都创建一个新的 CGContext。
关于objective-c - 重用 CGContext 导致奇怪的性能损失,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14071873/
我在为 MKMapOverlayView 创建的 CGContext 中执行一些 CG 绘图操作。在我的上下文中绘制之后,我创建了一个图像并将其粘贴到 MapKit 提供的上下文中。 - (void)
我有一个 CGBitmapContext (bitmapContext),我想将它的一些矩形部分 (rect) 绘制到当前 CGContext (context) >). 现在我就是这样做的: CGC
各位,这是我的代码: - (void) renderPageAtIndex:(NSUInteger)index inContext:(CGContextRef)ctx { //backgrou
我正在使用代码在 CGContext 上显示 pdf 页面 - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)context {
在我的 iPhone 项目中,我有一个 UIView,我在其中实现了 drawRect 方法: - (void)drawRect:(CGRect)rect { CGContextRef con
我正在尝试在 UIView draw(_:) 中创建自己的 CGContext。这里: override func draw(_ rect: CGRect) { //let c
我正在UIView drawRect函数中绘制一个形状,该形状涉及剪切路径,然后在后面添加彩色块,以便颜色具有剪切路径的形状。但是,由于某些原因,路径的线条无法顺利伸出;如果抗锯齿功能无法正常使用,
我正在使用以下代码缩小UIImage: let image = UIImage(contentsOfFile: imageUrl.path!)!.CGImage let
我正在尝试使用 Core Graphics 从另一个线程在自定义 UIView 中进行无限绘图。无法获取当前的 CGContext,因此我尝试创建一个新的。但我不知道如何将其应用到 View 中。 这
在测试我的应用程序是否存在任何错误时,我注意到在模拟器中,当我调用其中一个函数将图像设置为 UIImageView 时,会抛出一堆 CGContext 错误,并且图像永远不会被设置。然而,在我的设备上
我有一个 UIView,它有 3 个自定义 subview ,其类(目前)称为 LVStemp 并表示树中的节点。 LVStemp 的框架比节点本身大,因为它还包含一些位于节点外部的绘图(尚未编码)。
据我所知,您可以使用两种方法在 CGContext 中绘制渐变,即 drawLinearGradient 和 drawRadialGradient。我正在寻找一种定义椭圆渐变的方法,我可以在其中定义
我正在尝试初始化 CGContext ( API ) let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirector
问题:如何在 CGContext 下显示背景图片? 我使用 Storyboard创建了一个 View Controller ,并放置了一个带有全屏背景图像的 View 。然后,使用相同的 View C
我正在尝试绘制以相等角度分隔的矩形。为此,我首先绘制一个 CGPath,然后对上下文应用转换。我连续做了5次。这是我的代码和输出。如您所见,屏幕截图中的输出不正确,矩形倾斜,不知道为什么。需要知道我做
我正在用 CGContext 渲染一个 NSAttributedString,但是当它渲染文本时是颠倒的 :( 这是我想出的: override func draw(with box: PDFDisp
我编写了一个渲染函数,每 1/60 秒调用一次。如下所示。本质上,它以使用正弦的放射状图案呈现 40 条线。看起来像这样http://imgur.com/a/kPKtT .当我在我的 iPhone 6
我有这段代码可以呈现一个内部带有动态文本的自定义滑动条 handle 。问题是我无法将其缩放到视网膜分辨率。它可以在所有设备上正确绘制并且大小合适,但在视网膜上分辨率较低。如何更改此代码以使最终图像分
当具有不同颜色的路径使用 CGContext 绘制在先前路径的顶部时,如何删除路径? 最佳答案 CGContextBeginPath() 在创建新路径的过程中总是丢弃之前的路径。 关于ios - CG
伙计们! 我需要绘制一些图像到 CGContext。这是相关代码: CGContextSaveGState(UIGraphicsGetCurrentContext()); CGContextRef c
我是一名优秀的程序员,十分优秀!