this is borderline nitpicking. just because it is coded the way you
wouldnt doesnt mean we have to change it.

-igor

On Fri, Feb 13, 2009 at 12:23 PM, Antony Stubbs <[email protected]> wrote:
> Are we also not allowed to debate the merits of existing functionality?
>
> On 13/02/2009, at 7:46 PM, Igor Vaynberg wrote:
>
>> why are we even talking about it. nothing is broken in wicket,
>> correct? you are not forced to use it in your code. we like it. it
>> does not impact you. where is the problem?
>>
>> -igor
>>
>> On Fri, Feb 13, 2009 at 11:32 AM, Johan Compagner <[email protected]>
>> wrote:
>>>
>>> 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