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 >>>>>>>> >>>>>>>> >>>>>>>> >>>>>>>> >>>>>> >>>>> >>>> >>>> >>> > >
