I have an activity that constantly (several times per second) sends byte[] data to a service via AIDL. The service forwards these messages using a message–bundle* to a network thread’s handler. The network thread also constantly receives data, which it sends to the service‘s handler as message–bundle. The service sends this bundle to other activities through AIDL.
As you can tell, there is a lot of memory allocated for the bundles.
After viewing my memory allocations on DDMS I see that memory is allocated for:
- the
bundlebeing initialized - the hash map being created
- the
byte[]data I am adding as an entry to the hash table
I would like to reduce memory allocations to as little as possible.
Is there a better way to send byte[ ] across activities/threads than through messages with bundles?
*By message–bundle, I mean a message with a bundle as the data
Tried: to make a pool of bundle objects, but that didn’t work out too well – hard to manage between activities and I don’t know how to pre-allocate it with byte[] data…
Are those byte arrays that big that you really need to worry about? Without knowing anything of your app, I would guess that the bottleneck in the app you’re describing will be in the network handler, rather than the messaging between the Service and the Activity. Unless you’re leaking the Bundles somewhere, the GC should take care of all unused memory and restore it for your app to reuse.
If anything, I would try to keep those arrays small enough (to avoid allocating and recycling large amounts of memory at once) and send several small messages instead. That way, the app does not consume the available memory all at once and let the GC do its job with a relaxed schedule (i.e., when the CPU is idle) instead of forcing GC to collect the objects immediately.
Of course, what is “too big” or “small enough” is something you should test in your own app and measure what (if any) is the gain with one approach or other.
Update:
Copying verbatim from an android dev site article:
Based on your comment, I would reconsider whether the GC is relevant in your case. Heap limit may vary between 16 and 32 MB (and the upper limit is probably growing). Assuming 10 allocations per second, 64 bytes per allocation, you would allocate 1 MB every 30 minutes (approx). If the GC takes 200 ms to free that memory, the effect will be negligible. I understand that the numbers here do not consider the memory needed for the hash map nor the bundle, but they are still relevant to give you an idea of the orders of magnitude that we’re talking about. Now, consider how much time does a network request to grab those 64 bytes from the net. Even if it requires just 50 ms, that is 1/4 to 1/2 of the time needed by the GC, every net request. That does not even consider the time required by your Activity to process that data.
So, in conclusion, before restructuring your code in an attempt to improve its efficiency, make sure that the step you’re modifying is actually a bottleneck, or all your effort might be wasted. Just my $0.02.