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:
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:
- split 90 iterations 2 parts of 45.
- moved graphic context outside , clear after each iteration instead of creating new one.
- 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:
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:
- splitting whole rendering task subtasks. example, 90 drawings split 6 subtasks 15 drawings in each (the number of 15 found empirically).
- executing subtasks serially using
dispatch_after
small interval after each (0.05s in case). 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
Post a Comment