Performance optimization of Android learning notes Sparsearray

Source: Internet
Author: User

PS: Finally finished the test. The principle of microcomputer is fraught with crisis. But fortunately the database 89 points, still very gratified.

Learning content:

Use of Sparsearray in 1.Android.

After studying the horizontal level two menu yesterday, it was found that Sparsearray was used to replace the use of hashmap. So I looked up some of the relevant information, and I also carried out some tests on performance. First, let's talk about the principle of sparsearray.

Sparsearray (sparse array). He is an internal Android-specific API, and the standard JDK does not have this class. Inside Android to replace the Hashmap<integer,e> form, Using Sparsearray to save more memory space, Sparsearray also saves data with key and value. You only need to specify the type of value when you use it. and key does not need to be encapsulated into an object type.

Landlord according to the pro-test, Sparsearray storage data occupy the memory space is indeed smaller than the HashMap. A release of the test data is analyzed. Let's first look at the structural characteristics of both.

HashMap is a combination of arrays and linked lists, known as linked list hashes.

Sparsearray is a combination of simple arrays. Known as sparse arrays, there is no additional overhead when saving data. The structure is as follows:

This is the structure of the two, and we need to look at what the difference is ...

The first is insert:

HashMap the positive sequence insert:

New Hashmap<integer, string>long start_map =for (int i=0;i<max;i+ +) {     long map_memory =long end_map = System.currenttimemillis ()-  Start_map; System.out.println ("<---map insertion time--->" +end_map+ "<---map-occupied memory--->" +map_memory ");

Results after execution:
<---Map insertion time--->914
<---Map-occupied memory--->28598272

Sparsearray the positive sequence insert:

Sparsearray<string>sparse =NewSparsearray<string>(); LongStart_sparse =System.currenttimemillis (); for(inti=0;i<max;i++) {sparse.put (I, string.valueof (i));}LongSparse_memory =runtime.getruntime (). TotalMemory ();LongEnd_sparse = System.currenttimemillis ()-Start_sparse; System.out.println ("<---sparse insertion time--->" +end_sparse+ "<---sparse memory--->" +sparse_memory);//results after execution:<---Sparse insertion time--->611<---sparse memory--->23281664

We can see that the efficiency of the sparsearray is higher than that of the hashmap when the 100,000 data volume is inserted in the positive order. And it takes up less memory than HashMap. The positive order insertion here indicates that the value of I is an increment from small to large. The sequence depends on the value of I, not how it is performed inside the For loop ...

By running the results we can find that the Sparsearray is much faster than the hashmap when it is inserted in the positive order, and also saves a portion of the memory. There are many sayings on the internet about the efficiency of the two, many people will mistakenly think that sparsearray than the hashmap of the insertion and search efficiency faster, while others think that the hash lookup is certainly much faster than the binary search in Sparsearray.

In fact, I think that the essence of the recommended use of Sparsearray in Android when saving <Integer,Value> is not due to the reason of efficiency, It's about memory. We did see that Sparsearray is faster than hashmap when inserting. But this is just a positive sequence insert. Let's take a look at the case of reverse insertion.

hashmap Reverse Insert:

System.out.println ("<-------------data volume 100000 hash level small MAP reverse Insert--------------->"); HashMap<integer, string>map_2 =NewHashmap<integer, string>(); LongStart_map_2 =System.currenttimemillis ();  for(inti=max-1;i>=0;i--) {map_2.put (MAX-i-1, String.valueof (max-i-1)); }  LongMap_memory_2 =runtime.getruntime (). TotalMemory (); Longend_map_2 = System.currenttimemillis ()-start_map_2; System.out.println ("<---Map insertion time--->" +end_map_2+ "<---map takes up memory--->" +map_memory_2); //results after execution:<-------------data volume 100000 map reverse Insert---------------> <---Map insert time--->836<---map takes up memory--->28598272

Sparsearray Reverse Insert:

System.out.println ("<-------------data volume 100000 small sparsearray reverse insert--------------->"); Sparsearray<string>sparse_2 =NewSparsearray<string>();Longstart_sparse_2 =System.currenttimemillis (); for(inti=max-1;i>=0;i--) {sparse_2.put (i, string.valueof (MAX-i-1));}LongSparse_memory_2 =runtime.getruntime (). TotalMemory ();Longend_sparse_2 = System.currenttimemillis ()-start_sparse_2; System.out.println ("<---sparse insertion time--->" +end_sparse_2+ "<---sparse memory--->" +sparse_memory_2);//results after the execution<-------------amount of data 100000 sparsearray insertion time--->20222<------------------><---sparse Sparse occupied Memory--->23281664

Through the above results, we can still see, sparsearray and HashMap no matter how to insert, the same amount of data, the former will save a part of the memory, but efficiency? We can see that in reverse insertion, The insertion time of the sparsearray and the insertion time of the HashMap are far from an order of magnitude. Since Sparsearray each time it is inserted, it is used to determine whether the same value is inserted. So the reverse is the worst of sparsearray efficiency.

Sparsearray Insert Source code Let's take a quick look .

  Public voidPutintkey, E value) {        inti = Containerhelpers.binarysearch (Mkeys, msize, key);//two-point lookup.        if(I >= 0) {//if the current I exists in the array, it means that the same key value is inserted, and only the value is overwritten .Mvalues[i] =value; } Else{//if the array does not exist internally, then the returned value must be a negative number.i = ~i;//so I need to take the opposite number. //The value of I is less than msize indicates before this. The Mkey and mvalue arrays have been applied for space. Just the key value is deleted. Then when you save the new value again. No additional opening up of new memory space is required. Direct array Assignment .            if(I < msize && mvalues[i] = =DELETED) {Mkeys[i]=key; Mvalues[i]=value; return; }            //the GC () function needs to be called when the required space is exceeded, but there are useless values in the Mkey.            if(Mgarbage && msize >=mkeys.length) {GC (); //Search again because indices may have changed.i = ~Containerhelpers.binarysearch (Mkeys, msize, key); }            //If you need more space than the originally requested control, you need to open up new space for the key and value arrays.            if(Msize >=mkeys.length) {intn = arrayutils.idealintarraysize (msize + 1); //a new key and value array is defined. Needs to be greater than msize                int[] Nkeys =New int[n]; Object[] Nvalues=NewObject[n]; //log.e ("Sparsearray", "grow" + mkeys.length + "to" + N); //assigning an array is a copy operation. Assigns the values of the original Mkey array and the Mvalue array to the newly opened space. The purpose is to add a new key-value pair.System.arraycopy (Mkeys, 0, Nkeys, 0, mkeys.length); System.arraycopy (Mvalues,0, Nvalues, 0, mvalues.length); //assigns the array value: This simply expands the size of the array: The operation to put a key-value pair is not done here.Mkeys =Nkeys; Mvalues=nvalues; }            //if the value of I does not exceed the value of msize. Just enlarge the length of the Mkey .            if(Msize-i! = 0) {                //log.e ("Sparsearray", "move" + (msize-i));System.arraycopy (Mkeys, I, Mkeys, i + 1, msize-i); System.arraycopy (Mvalues, I, mvalues, I+ 1, msize-i); }            //here is the process used to complete the insert operation.Mkeys[i] =key; Mvalues[i]=value; Msize++; }    } 

This is the source code of the Sparsearray insert function. Each insertion method calls for a binary lookup. So this can cause a very bad situation in reverse The efficiency of the absolute lost to HashMap learned data structure of everyone knows. Map will make appropriate decisions about the conflict factor when it is inserted. There is a very good way to deal with conflicts. There is no need to traverse each value. Therefore, the efficiency of either reverse or positive sequence insertion depends on how the conflict is handled. So the time to insert is basically the same.

by inserting. We can still see the difference between the two.

Let's take a look again. Find First is HashMap.

System.out.println ("<-------------data volume 100000 map lookup--------------->"); HashMap<integer, String>map =NewHashmap<integer, string>();  for(inti=0;i<max;i++) {map.put (I, string.valueof (i)); }  LongStart_time =System.currenttimemillis ();  for(inti=0;i<max;i+=100) {map.get (i); }  LongEnd_time =system.currenttimemillis ()-start_time;    System.out.println (End_time); //results after the execution<!---------time to find: 175------------>

Search for Sparsearray:

System.out.println ("<-------------data volume 100000 Sparsearray find--------------->"); Sparsearray<string>sparse =NewSparsearray<string>();  for(inti=0;i<10000;i++) {sparse.put (I, string.valueof (i)); }  LongStart_time =System.currenttimemillis ();  for(inti=0;i<max;i+=10) {sparse.get (i); }  LongEnd_time =system.currenttimemillis ()-start_time;  System.out.println (End_time); //results after the execution<!-----------time to find: 239---------------->

I have also simply tested the efficiency of the search. a query for a data or a few data. The difference is still very small. When the amount of data is 100,000. Check the efficiency of 100,000 or map faster. When the data volume is 10000. The difference is even smaller. But the efficiency of the map's search has certainly won.

Actually, in my opinion. The main reason to use Sparsearray to replace HashMap when saving <Integer,E> is because of the memory relationship. We can see. The amount of data saved, whether large or small, The memory used by map is always greater than sparsearray. Data volume of 100,000 Sparsearray than HashMap to save 27% Memory. That is, to save memory space at the expense of efficiency. We know that Android's use of memory is extremely harsh. The maximum memory allowed for the heap area is only 16M. It is very easy to get an oom phenomenon. Therefore, the use of memory in Android is very important. So the official recommended to use Sparsearr Ay<e> to replace Hashmap<integer,e> officials did declare that the discrepancy would not exceed 50%. So sacrificing some of the efficiency in exchange for memory is actually a good choice in Android.

Performance optimization of Android learning notes Sparsearray

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.