I noticed that mkgmap does not intern any strings. In particular, this tile, generated by the splitter, fails to build with -Xmx3000m on 64-bit jdk under linux. With my patch, mkgmap generates the tile with -Xmx1000m.
<bounds minlat='55.1953125' minlon='9.4921875' maxlat='56.6015625' maxlon='11.513671875'/> This tile has 1m nodes. Among the nodes and ways on this tile, there are 12m tags, yet only 100k distinct tag key/value pairs; on average each value occurs 120 times. I explicitly do not use normal string interning because String.intern() strings are kept forever, and I want these strings to be GC'able after the tile is done. I trade GCability for having the occasional string duplicated in memory by flushing the interning table every 10k unique strings. This code is not presently multithread safe; Ideally there should be one string interning table for each parser/thread. Scott
diff --git a/src/uk/me/parabola/mkgmap/reader/osm/LossyIntern.java b/src/uk/me/parabola/mkgmap/reader/osm/LossyIntern.java new file mode 100644 index 0000000..5a6e07c --- /dev/null +++ b/src/uk/me/parabola/mkgmap/reader/osm/LossyIntern.java @@ -0,0 +1,26 @@ +package uk.me.parabola.mkgmap.reader.osm; + +import java.util.HashMap; + +/** Implement an interning string pool that resets its contents every N strings */ +public class LossyIntern { + static private HashMap<String,String> internmap = new HashMap<String,String>(); + static private int interncount=0; + + static public String intern(String s) { + String out=internmap.get(s); + if (out != null) { + return out; + } + interncount++; + if (interncount > 100000) { + internmap.clear(); + interncount = 0; + } + internmap.put(s,s); + return s; + } +} + + + diff --git a/src/uk/me/parabola/mkgmap/reader/osm/Tags.java b/src/uk/me/parabola/mkgmap/reader/osm/Tags.java index fd65b31..0c48318 100644 --- a/src/uk/me/parabola/mkgmap/reader/osm/Tags.java +++ b/src/uk/me/parabola/mkgmap/reader/osm/Tags.java @@ -65,12 +65,12 @@ public class Tags implements Iterable<String> { Integer ind = keyPos(key); if (ind == null) assert false : "keyPos(" + key + ") returns null - size = " + size + ", capacity = " + capacity; - keys[ind] = key; + keys[ind] = LossyIntern.intern(key); String old = values[ind]; if (old == null) size++; - values[ind] = value; + values[ind] = LossyIntern.intern(value); return old; } @@ -232,7 +232,7 @@ public class Tags implements Iterable<String> { for(int i = 0; i < capacity; ++i) { if(keys[i] != null && keys[i].startsWith(prefix)) { if(removePrefix) - map.put(keys[i].substring(prefixLen), values[i]); + map.put(LossyIntern.intern(keys[i].substring(prefixLen)), values[i]); else map.put(keys[i], values[i]); }
_______________________________________________ mkgmap-dev mailing list mkgmap-dev@lists.mkgmap.org.uk http://www.mkgmap.org.uk/mailman/listinfo/mkgmap-dev