you are forgetting that the value that is stored is also in mem
So if the value is an Integer object that is again an 4 bytes ci, 4 bytes oi
and 4 bytes value

But the IntHashmap is far from complex, i even like it if i just have int ->
value (which is where it is used for)
else i have to wrap those ints in a Integer object first (or auto box it
which i dont like to much)

so it is a big quicker, its smaller in mem size, and is easier to use when
you just have int keys.. i dont see any drawback

johan


On Fri, Feb 13, 2009 at 19:42, Tuomas Kärkkäinen <[email protected]>wrote:

> Hi,
>
> The int in Entry is a 32bit value so it takes 4 bytes of memory.
>
> In a 32bit JVM, a reference, ie. a pointer takes 4 bytes.  In a 64bit JVM
> it takes 8 bytes.
>
> HashMap's Entry consumes on a 32bit jvm:
> 4 bytes for the class identifier,
> 4 bytes for the object identifier,
> 4 bytes for the key
> 4 bytes for the value
> 4 bytes for the hash
> 4 bytes for next
>
> a total of 24 bytes.
>
> and on a 64bit jvm
> 4 bytes for the class identifier,
> 4 bytes for the object identifier,
> 8 bytes for the key
> 8 bytes for the value
> 4 bytes for the hash
> 8 bytes for next
>
> 36 bytes.
>
> IntHashMap's entry takes:
> 4 bytes for the class identifier,
> 4 bytes for the object identifier,
> 4 bytes for key
> 4 bytes for value
> 4 bytes for next
> 20 total on 32bits
> or
> 4 bytes for the class identifier,
> 4 bytes for the object identifier,
> 4 bytes for key
> 8 bytes for value
> 8 bytes for next
> 28 total on 64bits
>
> java.util.AbstractMap$SimpleEntry<K,V> and consequently
> java.util.concurrent.ConcurrentHashMap$WriteThroughEntry
> only has serialVersionUID, key and value.
> which is 24 bytes on 32bit and 32bytes on 64bit.
>
> As an aside, on my core2, the 32-bit hotspot seems to align objects on
> 8byte boundaries, so 20 and 24 bytes both consume 24 bytes.
>
> My personal conclusion would be that if there is a memory saving advantage
> to using IntHashMap, it is negligible.  Further, the accidental complexity
> IntHashMap introduces outweighs the memory savings.
>
> Br,
> Tuomas
>
> Quoting Johan Compagner <[email protected]>:
>
>  the serialized size doesnt have to be that different if you use Integer
>> key
>> objects because hashmap has its own special serialization where it doesnt
>> have to store everything thats in mem
>> but just the key/value combination
>>
>>
>> But in memory we have an Entry object:
>>
>> HashMap.Entry implements Map.Entry {
>>        final Object key;
>>        Object value;
>>        final int hash;
>>        Entry next;
>>
>> IntHashMap.Entry
>>    {
>>        final int key;
>>        Object value;
>>        Entry next;
>>
>> so you see thats one reference less per entry.
>>
>> Also the lookup could be faster because it doesnt have to calculate the
>> hash
>> on for example strings.
>>
>> The IntHashMap just skips over the object key hash and gives you the
>> option
>> to give that hash yourself.
>> This only works ofcourse for the same type of objects where the hash is
>> always different for any object, so it wont work as a replacement of
>> String
>> key, but it does for Integer key
>>
>> johan
>>
>>
>> On Fri, Feb 13, 2009 at 09:43, Tuomas Kärkkäinen  <
>> [email protected]>wrote:
>>
>>
>>  Hi,
>>>
>>> I couldn't gather from the javadoc when IntHashMap should be preferred
>>> over
>>> a regular HashMap, i.e. how many objects per map, what type of objects
>>> etc.
>>>
>>> I wrote a little program (copy pasted at the bottom) to see how much the
>>> size difference was for IntHashMap, java.util.HashMap and
>>> java.util.concurrent.ConcurrentHashMap.
>>>
>>> for 1 instance of new org.apache.wicket.Page(){};
>>> for 10 instances of new org.apache.wicket.Page(){};
>>> for 100 instances of new
>>> org.apache.wicket.ajax.form.AjaxFormSubmitTestPage();
>>>
>>> Br,
>>> Tuomas
>>>
>>> the results are as follows, respectively:
>>>
>>> --------------------------------------------------
>>>
>>> map implementation: org.apache.wicket.util.collections.IntHashMap -- size
>>> of outputstream: 54 bytes.
>>> map implementation: java.util.HashMap -- size of outputstream: 57 bytes.
>>> map implementation: java.util.concurrent.ConcurrentHashMap -- size of
>>> outputstream: 282 bytes.
>>> HashMap is 5.556% larger than IntHashMap.
>>> ConcurrentHashMap is 422.222% larger than IntHashMap.
>>>
>>> --
>>>
>>> map implementation: org.apache.wicket.util.collections.IntHashMap -- size
>>> of outputstream: 369 bytes.
>>> map implementation: java.util.HashMap -- size of outputstream: 399 bytes.
>>> map implementation: java.util.concurrent.ConcurrentHashMap -- size of
>>> outputstream: 624 bytes.
>>> HashMap is 8.130% larger than IntHashMap.
>>> ConcurrentHashMap is 69.106% larger than IntHashMap.
>>>
>>> --
>>>
>>> map implementation: org.apache.wicket.util.collections.IntHashMap -- size
>>> of outputstream: 24272 bytes.
>>> map implementation: java.util.HashMap -- size of outputstream: 24572
>>> bytes.
>>> map implementation: java.util.concurrent.ConcurrentHashMap -- size of
>>> outputstream: 24797 bytes.
>>> HashMap is 1.236% larger than IntHashMap.
>>> ConcurrentHashMap is 2.163% larger than IntHashMap.
>>>
>>>
>>> ----------
>>>
>>> /*
>>>  * Licensed to the Apache Software Foundation (ASF) under one or more
>>>  * contributor license agreements.  See the NOTICE file distributed with
>>>  * this work for additional information regarding copyright ownership.
>>>  * The ASF licenses this file to You under the Apache License, Version
>>> 2.0
>>>  * (the "License"); you may not use this file except in compliance with
>>>  * the License.  You may obtain a copy of the License at
>>>  *
>>>  *      http://www.apache.org/licenses/LICENSE-2.0
>>>  *
>>>  * Unless required by applicable law or agreed to in writing, software
>>>  * distributed under the License is distributed on an "AS IS" BASIS,
>>>  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
>>> implied.
>>>  * See the License for the specific language governing permissions and
>>>  * limitations under the License.
>>>  */
>>> package org.apache.wicket.util.collections;
>>>
>>>
>>> import java.io.IOException;
>>> import java.util.HashMap;
>>> import java.util.concurrent.ConcurrentHashMap;
>>>
>>> import org.apache.wicket.Page;
>>> import org.apache.wicket.util.io.ByteArrayOutputStream;
>>> import org.apache.wicket.util.io.WicketObjectOutputStream;
>>> import org.apache.wicket.util.tester.WicketTester;
>>>
>>> public class Tester
>>> {
>>>       private static final int NUMBER_OF_PAGES = 1;
>>>
>>>
>>>       public static void main(String[] args) throws Exception
>>>       {
>>>               int intHashMapSize = writeMap(populatedIntHashMap());
>>>               int hashMapSize = writeMap(populatedHashMap());
>>>               int concurrentHashMapSize =
>>> writeMap(populatedConcurrentHashMap());
>>>               double hashMapIsLargerPercetange =
>>> ((Double.valueOf(hashMapSize) / intHashMapSize) - 1) * 100;
>>>               double concurrentHashMapIsLargerPercetange =
>>> ((Double.valueOf(concurrentHashMapSize) / intHashMapSize) - 1) * 100;
>>>               System.out.printf("HashMap is %.3f%% larger than
>>> IntHashMap.%n", hashMapIsLargerPercetange);
>>>               System.out.printf("ConcurrentHashMap is %.3f%% larger than
>>> IntHashMap.%n",
>>>                       concurrentHashMapIsLargerPercetange);
>>>       }
>>>
>>>       private static int writeMap(Object map) throws IOException
>>>       {
>>>               ByteArrayOutputStream out = new ByteArrayOutputStream();
>>>               WicketObjectOutputStream objectOutputStream = new
>>> WicketObjectOutputStream(out);
>>>               objectOutputStream.writeObject(map);
>>>               System.out.printf("map implementation: %s -- size of
>>> outputstream: %d bytes.%n",
>>>                       map.getClass().getName(), out.size());
>>>               return out.size();
>>>       }
>>>
>>>       private static HashMap<Integer, Page> populatedHashMap()
>>>       {
>>>               new WicketTester();
>>>               HashMap<Integer, Page> map = new HashMap<Integer, Page>();
>>>               for (int i = 0; i < NUMBER_OF_PAGES; i++)
>>>               {
>>>                       map.put(i, createPage());
>>>               }
>>>               return map;
>>>       }
>>>
>>>       private static ConcurrentHashMap<Integer, Page>
>>> populatedConcurrentHashMap()
>>>       {
>>>               new WicketTester();
>>>               ConcurrentHashMap<Integer, Page> map = new
>>> ConcurrentHashMap<Integer, Page>();
>>>               for (int i = 0; i < NUMBER_OF_PAGES; i++)
>>>               {
>>>                       map.put(i, createPage());
>>>               }
>>>               return map;
>>>       }
>>>
>>>
>>>       private static IntHashMap<Page> populatedIntHashMap()
>>>       {
>>>               new WicketTester();
>>>               IntHashMap<Page> map = new IntHashMap<Page>();
>>>               for (int i = 0; i < NUMBER_OF_PAGES; i++)
>>>               {
>>>                       map.put(i, createPage());
>>>               }
>>>               return map;
>>>       }
>>>
>>>
>>>       private static Page createPage()
>>>       {
>>>               Page page = new Page()
>>>               {
>>>               };
>>>               page.detach();
>>>               return page;
>>>
>>>       }
>>> }
>>>
>>>
>>> Igor Vaynberg wrote:
>>>
>>>  exactly what the javadoc says, its a map that does not need to store a
>>>> key object. so it is smaller than a regular hashmap when serialized or
>>>> kept in memory.
>>>>
>>>> -igor
>>>>
>>>> On Thu, Feb 12, 2009 at 1:40 PM, Tuomas Kärkkäinen
>>>> <[email protected]> wrote:
>>>>
>>>>  Hi,
>>>>>
>>>>> I was looking at IntHashMap in wicket trunk.
>>>>>
>>>>> I couldn't figure out what it does.
>>>>>
>>>>> The implementation of hashcode for Integer is value, and the autoboxing
>>>>> of
>>>>> int to Integer comes out to Integer.valueOf(int) which is implemented
>>>>> as
>>>>> an
>>>>> array lookup for Integers in the range of -128 to 127, and beyond that
>>>>> it's
>>>>> just new Integer(int).  Page ids start at zero for each page in each
>>>>> session
>>>>> so most of the time they will be between zero and 127.
>>>>>
>>>>> Br,
>>>>> Tuomas
>>>>>
>>>>>
>>>>>
>>>>>
>>>
>>
>
>

Reply via email to