Long story short, I want to test my clone implementation of the android.os.Bundle class against that class to see which is better. I already know my version is likely going to be worse but I want to know how much worse. Are there any benchmarking tools out there for Android that I can use to see which object is bigger in memory and/or takes more processing time to store/retrieve values?
TL;DR:
I looked at the source code for the android.os.Bundle class, and I don't like how it stores and returns objects. It just stores them in a HashMap<String, Object>
and then casts to the requested object's class (like getString()
or getInt()
) using a ClassLoader. I feel that this, or any class casting for that matter, violates type-safety and introduces ambiguity at the programming level, which is what static typing aims to prevent, is it not?
I want to create a similar data container class that doesn't violate type-safety and doesn't introduce ambiguity. The logically simple yet obviously inefficient way would be to have a Map for each class I want to store.
What I decided on was a single HashMap<String, Integer>
that contains key-index mappings for an assortment of Lists for each class I want to store. For example a call to getString(String key)
will get the integer index associated with that key from the map if it exists and then try to get the object at that index in the associated ArrayList<String>
.
The only ambiguity here would be returning either null
(where the index doesn't exist in the List for that class) or the wrong object of the right class (where the mapped index exists but the original object stored with that key is in another List), which is really the programmer's responsibility to check for.
Objects of this class are only temporary containers, used to ship data from one place to another in a standardized fashion. They're not meant to stick around. They're also not used in the same manner as Bundles, although part of the reason I want a unified data container like this is to be able to easily convert to a Bundle
, JSONObject
, ContentValues
or Cursor
and back.
Or maybe the real question is: is casting really all that bad, or am I just going to extreme efforts to avoid it? I guess good programming is really the only way to avoid ambiguity in either case.
Update:
It looks like Bundle only uses the Classloader when it's unpacking itself from a Parcel, but it makes a call to unparcel() with every put() call. When retrieving it simply casts to the type that the method returns, inside a try-catch block for ClassCastException
. That's probably the simplest way to do it.
Are there any benchmarking tools out there for Android that I can use to see which object is bigger in memory and/or takes more processing time to store/retrieve values?
Yes, Android comes with a lot of great tools for developers, it's recommended to get to know them. Here you have official documentation link for a good start.
Switch to DDMS perspective, assuming you are in Eclipse.
Now, these views should be helpful to you in measuring memory:
To profile your application, see bottlenecks etc. use Traceview. To call it conveniently from Eclipse open Threads view and while running your program click the button with red circle, like "record button".
If it's possible to make your object be Serializable(by implementing Serializable interface). Then run the following code. It checks how much bytes your object takes:
private byte[] getBytes(Object o) {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
out = new ObjectOutputStream(bos);
out.writeObject(o);
return bos.toByteArray();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (out != null) {
out.close();
}
} catch (IOException ex) {
// ignore close exception
}
try {
bos.close();
} catch (IOException ex) {
// ignore close exception
}
}
return null;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With