How to get the in-memory size of an object in Andr

2019-02-12 09:18发布

问题:

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.

回答1:

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:

  • Allocation tracker. You can see which objects take how much memory. During a run you have to press buttons "Start tracking" and later "Get Allocations".
  • Heap. You can see what amount of memory is taken from the heap.

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".



回答2:

Are there any benchmarking tools out there for Android that I can use to see which object is bigger in memory

MAT.

and/or takes more processing time to store/retrieve values?

Traceview.

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?

Static typing is like a seasoning. How much is the right amount depends upon the taster.



回答3:

I would recommend MAT (memory analyser tool) too but there are caveats. Know that things like images are not stored in heap memory in certain versions e.g., before honeycomb, images are stored in native memory. Hence, checking the memory may not be very accurate all the time but I would recommend it in your case.



回答4:

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;
}


标签: java android oop