objective c - Reducing peak memory consumption -


i generate bitmaps using next simplified sake of simplicity code:

for (int frameindex = 0; frameindex < 90; frameindex++) {      uigraphicsbeginimagecontextwithoptions(cgsizemake(130, 130));      // making rendering on context.      // save current snapshot context.     uiimage *snapshot = uigraphicsgetimagefromcurrentimagecontext();     [self.snapshots addobject:snapshot];      uigraphicsendimagecontext(); } 

so nothing non-trivial gets complicated when operating system gives 30 mb of memory (in particular case watch os 2 nevertheless not os-dependent question) , exceeding quota, os kills application's process.

the next graph allocations instrument illustrates question:

enter image description here

it same graph different annotations of memory consumption - before, @ moment , after aforementioned code execution. can seen 5.7 mb of bitmaps have been generated , absolutely acceptable result. not acceptable memory consumption (44.6 mb) @ peak of graph - of memory eaten coreui: image data. given fact action takes place in background thread time of execution not important.

so questions: right approach decreasing memory consumption (maybe increasing execution time) fit memory quota , why memory consumption increased despite uigraphicsendimagecontext called?

update 1: think splitting whole operation using nsoperation, nstimer etc. trick still trying come synchronous solution.

tried gather answers , tested next piece of code:

uigraphicsbeginimagecontextwithoptions(cgsizemake(130, 130)); (int frameindex = 0; frameindex < 45; frameindex++) {      // making rendering on context.      @autoreleasepool {         uiimage *snapshot = uigraphicsgetimagefromcurrentimagecontext();         [self.snapshots addobject:snapshot];     }     cgcontextclearrect(uigraphicsgetcurrentcontext(), cgsizemake(130, 130)); }  (int frameindex = 0; frameindex < 45; frameindex++) {      // making rendering on context.      @autoreleasepool {         uiimage *snapshot = uigraphicsgetimagefromcurrentimagecontext();         [self.snapshots addobject:snapshot];     }     cgcontextclearrect(uigraphicsgetcurrentcontext(), cgsizemake(130, 130)); } uigraphicsendimagecontext(); 

what has changed:

  1. split 90 iterations 2 parts of 45.
  2. moved graphic context outside , clear after each iteration instead of creating new one.
  3. wrapped taking , storing snapshots in autorelease pool.

as result - nothing changed, memory consumption remains on same level.

also, if remove taking , storing snapshot @ decrease memory consumption 4 mb i.e. less 10%.

update 2:

doing rendering timer every 3 seconds generates next graph:

enter image description here

as see memory not freed (to precise - not fully) if rendering divided time intervals. tells me memory not freed until object performs rendering exists.

update 3:

the problem has been solved combining 3 approaches:

  1. splitting whole rendering task subtasks. example, 90 drawings split 6 subtasks 15 drawings in each (the number of 15 found empirically).
  2. executing subtasks serially using dispatch_after small interval after each (0.05s in case).
  3. and last , important. avoid memory leak on last graph - each subtask should executed in context of new object. example:

    self.snapshots = [[snaphotrender new] rendersnapshotsinrange:[0, 15]];

thanks answering @emiliopelaez closest right answer.

i think problem doing snapshots in same context (the context for loop in). believe memory not being released until context ends, when graph goes down.

i suggest reduce scope of context, instead of using loop draw frames keep track of progress ivars , draw 1 frame; whenever finish rendering frame, can call function again dispatch_after , modify variables. if delay 0, allow context end , clean memory no longer being used.

ps. when mean context don't mean graphics context, mean scope in code.


Comments