Getting the most from map data structures in Android
Ruben Saboridoacute; [1]·Rodrigo Morales1·
Foutse Khomh1·Yann-Gael Guuml; ehacute; eneucacute; 1·
Giuliano Antoniol1
Published online: 2 March 2018
copy; Springer Science Business Media, LLC, part of Springer Nature 2018
Abstract A map is a data structure that is commonly used to store data as key– value pairs and retrieve data as keys, values, or key–value pairs. Although Java offers different map implementation classes, Android SDK offers other implementations supposed to be more efficient than HashMap: ArrayMap and SparseArray variants
(SparseArray, LongSparseArray, SparseIntArray, SparseLongArray, and SparseBooleanArray). Yet, the performance of these implementations in terms of CPU time, memory usage, and energy consumption is lacking in the official Android documentation; although saving CPU, memory, and energy is a major concern of users wanting to increase battery life. Consequently, we study the use of map implementations by Android developers in two ways. First, we perform an observational study of 5713 Android apps in GitHub. Second, we conduct a survey to assess developersrsquo; perspective on Java and Android map implementations. Then, we perform an experimental study comparing HashMap, ArrayMap, and SparseArray variants map implementations in terms of CPU time, memory usage, and energy consumption. We conclude with guidelines for
Ruben Saboridoacute;
ruben.saborido-infantes@polymtl.ca
Rodrigo Morales rodrigo.morales@polymtl.ca
Foutse Khomh foutse.khomh@polymtl.ca
Yann-Gael Guuml; ehacute; eneucacute; yann-gael.gueheneuc@polymtl.ca
Giuliano Antoniol giulio.antoniol@polymtl.ca
choosing among the map implementations: HashMap is preferable over ArrayMap to improve energy efficiency of apps, and SparseArray variants should be used instead of HashMap and ArrayMap when keys are primitive types.
Keywords Android · Map data structure · Map implementations · CPU usage · Memory usage · Energy consumption
1 Introduction
Android is a popular open-source operating system developed by Google for mobile devices. Android is successful in part due to the availability of hundreds of thousands of apps written using the Android Software Development Kit (SDK) and Java.
Google has recently mentioned, during the Google I/O Developers Festival in May 2017, that there are two billion active Android devices in the world.[2] Developers should manage resources mindfully because emerging markets own a significant share of this installed base; for example, there are more Android users in India than in the United States of America. However, many of the devices sold in emerging markets are resource constrained. To mitigate these factors, Google has also announced Android Go, which is a lightweight version of the operative system that is optimized for low-cost devices with less than one gigabyte of memory. Hundreds of millions of people around the world are making their way online for the first time, and Google wants to create a better experience for them. The new Android experience will ship in 2018 for all Android devices that have up to one gigabyte of memory. Google recommends taking a look at the Building for Billions[3] to learn about the importance of offering a useful offline state, reducing apk size, and minimizing memory and battery usages.
Previous empirical studies indicated that software engineers can help reduce energy consumption by considering the energy impacts of their design and implementation decisions, e.g., using dark colors in their graphical user interfaces (Li et al. 2014), considering the performance of different data structures (Manotas et al. 2014), or removing anti-patterns in Android apps (Morales et al. 2017). Hasan et al. (2016) showed that the Java implementations of various data structures differ significantly in terms of energy consumption, depending on the operations (insertions, iterations, and queries). They made developers aware of the consequences of their decisions. e.g., while List and Set collections consume about the same energy for the same operations, HashMap is the most energy-efficient Java map implementation. A map is a data structure used to store and retrieve data as key–value pairs, each key being unique.
Android SDK offers specialized map implementations and a series of video tutorials discussing performance issues.[4] The Android developersrsquo; reference documentation states that “ArrayMapis designed to be more memory efficient than a traditional HashMap”.[5]
When keys are defined as integer primitive types, the documentation also states that “SparseArrayis designed to be more memory efficient than HashMapto map integers to objects”.[6] The same is stated about LongSparseArray and long primitive types used as keys.[7] When keys are defined as integer primitive types and values are defined as integer, long, or boolean primitive types, the documentation also states that SparseIntArray,[8]SparseLongArray,[9] and SparseBooleanArray,[10] respec
摘要:映射是一种数据结构,通常用于将数据存储为键-值对,并将数据检索为键、值或键-值对。虽然Java提供了不同的映射实现类,但Android SDK提供了比HasMap更有效的其他实现:ArrayMap和SabSRAIL(SpasSurix,LongSparseArray,SpulsInTayLay,SabelSunGrand,SabeSoBoLoAlnAln阵列)。然而,这些实现在CPU时间、内存使用和能耗方面的性能在官方的Android文档中缺乏,尽管节省CPU、内存和能源是希望延长电池寿命的用户的主要关注点。因此,我们从两个方面研究了Android开发人员对映射的使用。首先,我们对Github中的5713个Android应用程序进行了观察研究。其次,我们进行了一项调查,以评估开发者对Java和Android映射实现的看法。然后,我们对HashMap、ArrayMap和SparseArray变量映射实现在CPU时间、内存使用和能耗方面进行了实验研究。
关键词:android 映射数据结构 映射实现 cpu使用 内存使用 能耗
1 简介
Android是谷歌为移动设备开发的一种流行的开源操作系统。Android之所以成功,部分原因在于使用Android软件开发工具包(SDK)和Java编写的成百上千个应用程序的可用性。
谷歌最近在2017年5月的谷歌I/O开发者节上提到,世界上有20亿台活跃的Android设备。开发人员应谨慎管理资源,因为新兴市场在这一安装基础上占有很大份额;例如,印度的Android用户比美国的多。然而,在新兴市场销售的许多设备都受到资源限制。为了缓解这些因素,谷歌还发布了Android Go,这是一个操作系统的轻量级版本,针对内存不足1千兆字节的低成本设备进行了优化。世界各地数亿人首次在网上购物,谷歌希望为他们创造更好的体验。新的Android体验将于2018年发布,适用于所有内存高达1 GB的Android设备。google建议您看看这座亿万富翁大厦,了解提供一个有用的离线状态、减少apk大小以及最小化内存和电池使用的重要性。
以前的经验研究表明,软件工程师可以通过考虑其设计和实现决策的能量影响来帮助降低能耗,例如,在图形用户界面中使用深色,考虑不同数据结构的性能,或删除Android应用程序中的反模式。哈桑等人(2016)表明,根据操作(插入、迭代和查询),各种数据结构的Java实现在能量消耗方面显著不同。他们让开发人员意识到他们的决策的后果。例如,虽然列表和集合消耗相同的能量用于相同的操作,但是HashMap是最节能的Java映射实现。映射是一种数据结构,用于存储和检索作为键-值对的数据,每个键都是唯一的。
android sdk提供专门的映射实现和一系列讨论性能问题的视频教程。android开发人员的参考文档指出,“ArrayMap被设计成比传统的HashMap更节省内存”。 当键被定义为整数基元类型时,文档还指出“SparseArray被设计为比HashMap更节省内存,以便将整数映射到对象”。对于用作键的longParseArray和long基元类型也作了同样的说明。当键被定义为整型基元类型,并且值被定义为整型、长型或布尔型基元类型时,文档还指出Sparseintarray、Sparselongarray,parseBooleanarray和SparseBooleanarray分别被设计为比传统的HashMap更高效的内存。除了先前的Android Studio,官方的Android集成开发环境(IDE),警告“使用新的SparseArray代替新的HashMaplt;integer,objectgt;()以获得更好的性能”(对SparseArray变体也给出了类似的警告)。因此,ArrayMap和SparseArray应该比HashMap更受欢迎,根据Android开发者的参考,至少对于包含多达数百个元素的地图来说是这样。对于ArrayMap和SparseArray,文档声明“此实现不适用于可能包含大量项的数据结构。它通常比传统的哈希图慢。“
然而,文件是模糊的,因为(1)它没有提供有关效率的支持证据和定量信息;(2)尽管它不鼓励在包含大量元素的映射中使用它们,但它没有提供更精确的数字(例如,性能信息和要考虑的阈值水平)。因此,尽管当前的文档提高了开发人员对映射实现的优势和局限性的认识,但它没有提供具体的证据,可用于对最适合其应用程序的实现做出明智的决策。“大量”和“一般较慢”之类的表达式是模糊的,它们对开发人员一点帮助都没有。除了前面的内容,文档中没有提到能耗,也没有提到不同映射相关操作和数据大小的性能。在本文中,我们研究了与HashMap相比,android提供的map实现ArrayMap和SparseArray变体的性能,并为开发人员做出明智的决策提供指导。首先,我们对移动应用程序中地图实现的使用进行了最大规模的观察研究。我们分析了截至2016年11月23日在GitHub上托管并在官方Android市场(Google Play)上可用的所有Android应用程序。我们报告(1)HashMap是使用的映射实现,(2)很少使用ArrayMap和SparseArray变量,(3)即使SparseArray变体看起来更合适,也经常采用HashMap。其次,我们调查分析应用程序的Android开发人员,了解他们对映射实现的看法。我们联系了656名开发商,收到了118份(18%)完成的调查。我们报告说,开发人员对不同的android映射实现的含义相当熟悉,他们使用HashMap是因为它是众所周知的。但是,如果大多数开发人员(86%)对其他实现的性能有更具体的信息,他们将替换HashMap。因此,我们对HashMap、ArrayMap和SparseArray变量实现时CPU和内存使用以及能耗进行了实证研究。我们发现虽然前者在内存使用方面比后者好一些,但ArrayMap比HashMap节能和慢一些。我们估计HashMap比ArrayMap平均快13%,消耗的能量比ArrayMap少16%。但是,ArrayMap使用的内存(6%)比HashMap少。如果键是原始类型,我们会发现对于所有性能指标和大多数操作,SparseArray变量比HashMap更有效。使用HashMap而不是SparseArray变体的平均成本CPU时间增加25%,内存增加62%,能量增加6%。使用ArrayMap而不是SparseArray所产生的成本与HashMap类似。
我们得出的结论是,Android开发人员更喜欢HashMap,因为他们不愿意通过预测效率可能的提高来采用Android实现。虽然使用Android映射实现可以真正节省CPU和内存使用,并降低能耗。对于大多数常见的与映射相关的操作,我们提供了在不同的映射实现之间进行选择的准则,并考虑到它们的性能。因此,我们作出以下努力:
——定量分析2016年12月在GitHub提供的所有5713个Android应用程序中映射的使用情况。
——118名Android开发者对不同映射的知识和使用情况的调查。
——定量分析使用HashMap、ArrayMap或SparseArray变量对性能指标的影响。
我们通过提供复制包、我们的调查、开发的所有Android应用程序和测试案例、脚本和收集的数据来确保研究的可复制性。
在下文中,第2节讨论了映射数据结构的Java和Android实现。第3节描述了我们在Android应用程序中使用映射实现的观察研究。第4节介绍了Android开发者的调查。第5节总结了我们评估MAP实现性能的实验。第6节为开发人员提供了指导。第7节警示对我们结果有效性的威胁。第8节总结了相关工作。第9节总结了未来的工作。
2 背景
Java在包Java.UTIL中提供了三种通用映射实现:HashMap、LinkedHashMap和TeeMeAP。HashMap是HashMap.entry实例的数组,即非基元键和值对。当把一个键-值对放入HashMap中时,会计算出该键的哈希代码,并使用它来获取数组中条目的索引。linked HashMap是一个哈希表和链表的组合,用于实现具有可预测迭代顺序的映射。与HashMap相反,linked HashMap维护其所有条目的双重链接列表,该列表定义了迭代顺序。treemap是另一个使用tree来存储键-值对的实现。按排序顺序,允许快速检索。
HashMap和linkedHashMap的构造函数有两个影响其性能的可选参数:容量和负载系数。默认的负载系数是0.75,在官方文档中,它在CPU和内存使用之间提供了一个“良好”的权衡。默认容量是创建哈希表时哈希表中的存储桶数,插入16times;0.75=13个元素时将进行大小调整。这些映射实现的缺点是使用非基元类型。(auto-)装箱是基本类型所必需的,它在插入时创建额外的对象。最后,每次压缩或扩展映射下的数组时,都必须重新排列条目,并且两个实现都必须存储键及其哈希代码,以避免冲突,但会增加内存使用量。
Android提供了自己的映射实现。实现ArrayMap应该比HashMap更节省内存。ArrayMap将其映射保存在一个数组中,每个项使用一个整数哈希代码数组和一个键-值对的对象数组。因此,它避免为放入映射中的每个条目创建额外的对象,并更积极地控制数组大小的增长(增长它们只需要复制数组中的条目,而不需要重建哈希映射)。虽然这个实现的内存效率比HashMap高,但ArrayMap仍然不能解决(自动)装箱问题,因为它的put方法仍然将两个对象作为参数。
如果键是整数,android建议使用SparseArray将整数映射到对象。SparseArray的目标是比HashMap更节省内存。它避免(自动)装箱键,并且它的实现不会为每个映射增加一个入口对象的额外开销。Android提供了不同SparseArray变体,可以映射到不同的基元类型:将长整型键映射到对象的longParseArray,以及将整数映射到sparseintarray、sparselongarray和sparsebooleanarray,以及将不同基元类型映射到值对象的sparseintarray。
ArrayMap和SparseArray变体都位于Android API提供的android.uti包中,但ArrayMap仅在Android API级别19(kitkat)及更高版本中提供。ArrayMap的另一个实现位于android.support.v4.util包中,适用于较旧版本的android。我们研究这两种实现,但只报告android.util包中实现的结果,因为针对android api 19及更高版本的应用程序将在90%以上的活动设备上运行。
3观察研究
我们研究了Android开发人员对Java映射实现的使用和Android映射实现时ArrayMap和sarsarray的使用情况。我们进行这项研究是为了分析映射实施的普遍性。我们定义了以下研究问题,我们通过对Github上可用的Android应用程序的观察研究来回答。
问题1:Android的开发者使用映射?
3.1对象
我们从Github(知识库查询和访问日期:2016年12月)中选择了所有在官方Android Marketplace中作为Android应用程序发布的项目,即在readme.md文件中包含指向Google Play Marketplace链接的所有项目。我们选择开源应用程序来研究源代码中地图实现的流行性。
3.2程序
我们开发了一个python脚本来自动选择和下载包含来自github的每个现有android项目的源代码的zip文件。因此,我们得到了5713Android应用程序。我们还开发了一个BASH脚本来处理所有应用程序的源代码,寻找通用Java映射实现(Hasmap、LinkedHashMap和TreeMap)以及Android映射实现。(ArrayMap和SparseArray变体)。此脚本生成一个逗号分隔值(CSV)文件。对于每个Android应用程序和映射实现,该文件包含一个布尔值,用于指定应用程序在其源代码中是否出现一个或多个映射实现。
3.3 结果
我们发现,超过5713个应用程序,1713(30%)个应用程序至少有一个Java映射实现的发生。对于ArrayMap和SparseArray,419(7%)个应用程序有一个或多个这些映射实现。总的来说,5713个应用程序中,超过2132(37%)个使用任何研究过的映射实现。
我们发现,HashMap是最常用的Java映射实现与1640个应用程序(77%),而其他使用较少。我们发现282个(13%)应用程序使用LinkedHashMap,179(8%)个应用程序使用Treemap。请注意,可以在相同的应用程序。关于Android地图的实现,我们发现ArrayMap和SparseArray变体很少被Android开发人员使用。只有19(1%)和413(7%)个应用程序分别使用了ArrayMap或SparseArray。
表1显示了Java和Android映射实现的任意组合出现的一个或多个应用程序的数量和百分比。第二列显示了一个或多个出现ArrayMap和一个或多个Java映射实现的应用程序的数量和百分比。第三列与前一列相似,但用于SparseArray。最后一列显示了应用程序的数量和百分比,这些应用程序有一个或多个出现的ArrayMap和SpasRaymap映射以及一个或多个Java映射实现的出现。我们观察到ArrayMap和SparseArray变体与HashMap结合使用。这是SparseArray变体所期望的,因为当键是基元类型时使用这些映射实现,而HashMap可以使用将非基元类型存储为键或值。但是,ArrayMap可以用
资料编号:[3565]
以上是毕业论文外文翻译,课题毕业论文、任务书、文献综述、开题报告、程序设计、图纸设计等资料可联系客服协助查找。