简体   繁体   English

如何在Android或性能基准测试中获取对象的内存大小?

[英]How to get the in-memory size of an object in Android, or performance benchmarks?

Long story short, I want to test my clone implementation of the android.os.Bundle class against that class to see which is better. 长话短说,我想测试我对该类的android.os.Bundle类的克隆实现,看看哪个更好。 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? 是否有适用于Android的基准测试工具,我可以使用它来查看哪个对象在内存中更大和/或需要更多处理时间来存储/检索值?

TL;DR: 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. 我查看了android.os.Bundle类的源代码,我不喜欢它如何存储和返回对象。 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. 它只是将它们存储在HashMap<String, Object> ,然后使用ClassLoader强制转换为请求对象的类(如getString()getInt() )。 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. 逻辑上简单但效率明显低的方法是为我想要存储的每个类创建一个Map。

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. 我决定的是单个HashMap<String, Integer> ,它包含我想要存储的每个类的各种列表的键索引映射。 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> . 例如,对getString(String key)的调用将从映射中获取与该键相关联的整数索引(如果存在),然后尝试在关联的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. 这里唯一的歧义是返回null (该类的List中不存在索引)或右类的错误对象(映射索引存在但原始对象与该键存储在另一个List中) ),这确实是程序员检查的责任。

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. 它们也没有像Bundles一样使用,虽然我想要像这样的统一数据容器的部分原因是能够轻松转换为BundleJSONObjectContentValuesCursor并返回。

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. 看起来Bundle只在从包中解压缩时才使用Classloader,但它会在每次调用put()时调用unparcel()。 When retrieving it simply casts to the type that the method returns, inside a try-catch block for ClassCastException . 检索它时,只需转换为方法返回的类型,在ClassCastException的try-catch块内。 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? 是否有适用于Android的基准测试工具,我可以使用它来查看哪个对象在内存中更大和/或需要更多处理时间来存储/检索值?

Yes, Android comes with a lot of great tools for developers, it's recommended to get to know them. 是的,Android为开发人员提供了许多很棒的工具,建议他们去了解它们。 Here you have official documentation link for a good start. 在这里,您可以获得官方文档链接,以获得良

Switch to DDMS perspective, assuming you are in Eclipse. 假设您在Eclipse中,切换到DDMS透视图。

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 . 要分析您的应用程序,请查看瓶颈等。使用Traceview To call it conveniently from Eclipse open Threads view and while running your program click the button with red circle, like "record button". 要从Eclipse打开Threads视图方便地调用它,在运行程序时单击带有红色圆圈的按钮,如“record button”。

Are there any benchmarking tools out there for Android that I can use to see which object is bigger in memory 有没有适用于Android的基准测试工具,我可以使用它来查看哪个对象在内存中更大

MAT. 垫。

and/or takes more processing time to store/retrieve values? 和/或需要更多的处理时间来存储/检索值?

Traceview. 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. 适量的数量取决于品酒师。

I would recommend MAT (memory analyser tool) too but there are caveats. 我也推荐使用MAT(内存分析器工具),但有一些警告。 Know that things like images are not stored in heap memory in certain versions eg, 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. 因此,检查内存可能不是一直非常准确,但我会在你的情况下推荐它。

If it's possible to make your object be Serializable(by implementing Serializable interface). 如果可以使您的对象可序列化(通过实现Serializable接口)。 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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM