JPJson icon indicating copy to clipboard operation
JPJson copied to clipboard

Memory Leaks with JPAsyncJsonParser

Open Kirow opened this issue 11 years ago • 4 comments

I'm pulling gzipped data from the internet, and call [parser parseBuffer:data] in didRecieveData: method. It works super fast on my desktop/simulator. But I've notice tons of memory leaks on the iOS device.

Leaks comes from CFDataBuffer I think. Not sure how to fix it.

Kirow avatar Nov 10 '14 13:11 Kirow

I will build the sample project NSURLConnectionDownload and try to reproduce the error. The project is somewhat outdated and needs a few fixes and should be migrated to Xcode 6.1 (which I will incorporate into a bug fix and update release). It also needs a setup for a web service. I try to get this done this week end.

couchdeveloper avatar Nov 13 '14 23:11 couchdeveloper

Don't worry about sample project. I will add repo for it on weekends.

Kirow avatar Nov 14 '14 07:11 Kirow

https://github.com/Kirow/Memory-Leak-Sample

Kirow avatar Nov 15 '14 12:11 Kirow

I could locate and fix a memory leak in the CFDataBuffer class. Furthermore, there was a memory leak when using one certain optimization opportunity when creating the JSON representation: USE_OPTIMIZED_IMMUTABLE_CALLBACKS.

The first leak in the CFDataBuffer class was quite a severe one which leaked the whole input buffer when using the async parser and was introduced when porting CFDataBuffer to C+11 and implementing move c-tor and move assignment operators. :/ (I haven't used the async parser for a long time).

The second one is not yet fixed - but it doesn't occur when disabling this kind of optimization. I'll try to fix this one soon.

Two other potential leaks (minor) have been fixed in the Unit Test code and related helper functions.

There were also one other minor bug which has been fixed.

The project can now be compiled with Xcode 6.1 and should use iOS deployment target >= 7.0.

Hope this will fix most of your issues ;)

One other thing which could be improved when using the async parser:

The implementation of parseBuffer: could possibly be more efficient: A NSData potentially represents its bytes not necessarily through one contiguous range of bytes, but possibly through an array of smaller buffers. These internal buffers (that is, a contiguous byte range for each buffer) can be accessed with:

- (void)enumerateByteRangesUsingBlock:(void (^)(const void *bytes,
                                        NSRange byteRange,
                                        BOOL *stop))block

Now, the class CFDataBuffer could be replaced by a similar variant that takes that byte range and does not allocate a buffer itself (like CFDataBuffer would do). The new replacement class would just hold the pointer and the size of the byte range.

That way, we could leverage the "scatter/gather buffers" and avoid the allocation and composition of a big contiguous buffer which is created when simply using [data bytes]. The underlying implementation doesn't need to change - just that kind of buffer class.

couchdeveloper avatar Nov 17 '14 23:11 couchdeveloper