Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 9060695
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 16, 20262026-06-16T15:17:43+00:00 2026-06-16T15:17:43+00:00

My class is rendering images offscreen. I thought reusing the CGContext instead of creating

  • 0

My class is rendering images offscreen. I thought reusing the CGContext instead of creating the same context again and again for every image would be a good thing. I set a member variable _imageContext so I would only have to create a new context if _imageContext is nil like so:

if(!_imageContext)
    _imageContext = [self contextOfSize:imageSize];

instead of:

CGContextRef imageContext = [self contextOfSize:imageSize];

Of course I do not release the CGContext anymore.

These are the only changes I made, turns out that reusing the context slowed down rendering from about 10ms to 60ms. Have I missed something? Do I have to clear the context or something before drawing into it again? Or is it the correct way to recreate the context for each image?

EDIT

Found the weirdest connection..

While I was searching for the reason why the app’s memory is incredibly increasing when the app starts rendering the images, I found the problem was where I set the rendered image to an NSImageView.

imageView.image = nil;
imageView.image = [[NSImage alloc] initWithCGImage:_imageRef size:size];

It looks like ARC is not releasing the previous NSImage. First way to avoid that was to draw the new image into the old one.

[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];

The memory problem was gone and what happened to the CGContext-reuse problem?
Not reusing the context now takes 20ms instead of 10ms – of course drawing into an image takes longer than just setting it.
Reusing the context also takes 20ms instead of 60ms. But why? I don’t see that there could be any connection, but I can reproduce the old state where reusing takes more time just by setting the NSImageView‘s image instead of drawing it.

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-16T15:17:44+00:00Added an answer on June 16, 2026 at 3:17 pm

    I investigated this, and I observe the same slowdown. Looking with Instruments set to sample kernel calls as well as userland calls shows the culprit. @RyanArtecona’s comment was on the right track. I focused Instruments in on the bottom most userland call CGSColorMaskCopyARGB8888_sse in two test runs (one reusing contexts, the other making a new one every time), and then inverted the resulting call tree. In the case where the context is not reused, I see that the heaviest kernel trace is:

    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
    

    This is the kernel zeroing out pages of memory that are being faulted in by virtue of CGSColorMaskCopyARGB8888_sse accessing them. What this means is that the CGContext maps VM pages to back the bitmap context but the kernel doesn’t actually do the work associated with that operation until someone actually accesses that memory. The actual mapping/fault happens on first access.

    Now let’s look at the heaviest kernel trace when we DO reuse the context:

    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
    

    This is the kernel copying pages. My money would be on this being the underlying copy-on-write mechanism that delivers the behavior @RyanArtecona was talking about in his comment:

    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.

    In the contrived case I used to test, the non-reuse case took 3392ms to execute and the reuse case took 4693ms (significantly slower). Considering just the single heaviest trace from each case, the kernel trace indicates that we spend 668.0ms zero filling new pages on the first access, and 1327.0ms writing into the copy-on-write pages on the first write after the image gets a reference to those pages. This is a difference of 659ms. This one difference alone accounts for ~50% of the gap between the two cases.

    So, to distill it down a little, the non-reused context is faster because when you create the context it knows the pages are empty, and there’s no one else with a reference to those pages to force them to be copied when you write to them. When you reuse the context, the pages are referenced by someone else (the image you created) and must be copied on the first write, so as to preserve the state of the image when the state of the context changes.

    You could further explore what’s going on here by looking at the virtual memory map of the process as you step through in the debugger. vmmap is the helpful tool for that.

    Practically speaking, you should probably just create a new CGContext every time.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

How to add value to this form.content before rendering class myform(forms.Form): title = forms.CharField(max_length
I have an interface IRenderable and a class that manages rendering all instances of
I'm rendering this Cmenu but the active class isn't showing on the li element
Using OpenGL ES I am rendering a simple cube class that draws it at
i'm creating a web page which contains a few dynamically generated images. in my
Using Django I'm creating a thumbnail of an image uploaded using a standard ImageField,
The browser would render a webpage faster if it knows the images dimensions. But
i have a problem with rendering image on RDL file in reporting services (SQL
I'm using the Ignition class RemoteImageView to asynchronously download and show images. RemoteImageView is
I'm trying to present different background images based on a css class that is

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.