package org.trie4j.test; import java.lang.reflect.Array; import java.util.HashMap; import java.util.Map; import java.util.Stack; import org.trie4j.Trie; import org.trie4j.bv.BytesConstantTimeSelect0SuccinctBitVector; import org.trie4j.bv.BytesRank1OnlySuccinctBitVector; import org.trie4j.bv.BytesSuccinctBitVector; import org.trie4j.bv.LongsConstantTimeSelect0SuccinctBitVector; import org.trie4j.bv.LongsRank1OnlySuccinctBitVector; import org.trie4j.bv.LongsSuccinctBitVector; import org.trie4j.bv.SuccinctBitVector; import org.trie4j.louds.TailLOUDSTrie; import org.trie4j.louds.bvtree.BvTree; import org.trie4j.louds.bvtree.LOUDSBvTree; import org.trie4j.util.IntArray; public class TrieMemoryUsage { public void print(Trie trie){ if(trie instanceof TailLOUDSTrie){ printTailLOUDSTrie((TailLOUDSTrie)trie); } else{ System.out.println("unknown trie: " + trie.getClass().getName()); } } public void printTailLOUDSTrie(TailLOUDSTrie trie){ p.println(trie.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ p.print("bvTree: "); int bvTree = bvTree(trie.getBvTree()); total += bvTree; } finally{ p.unnest(); } p.println("}; %d.", total); } public int bvTree(BvTree bvTree){ if(bvTree instanceof LOUDSBvTree){ return loudsBvTree((LOUDSBvTree)bvTree); } else{ throw new RuntimeException("unknown BvTree"); } } public int loudsBvTree(LOUDSBvTree lbt){ p.println(lbt.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ int sbv = cp("sbv", lbt.getSbv()); total = sbv; } finally{ p.unnest(); } p.println("}; %d.", total); return total; } public int cp(String name, SuccinctBitVector sbv){ if(sbv instanceof MonitoredSuccinctBitVector){ return cp(name, ((MonitoredSuccinctBitVector)sbv).getOriginal()); } else if(sbv instanceof BytesSuccinctBitVector){ return cp(name, (BytesSuccinctBitVector)sbv); } else if(sbv instanceof BytesRank1OnlySuccinctBitVector){ return bytesRank1Sbv((BytesRank1OnlySuccinctBitVector)sbv); } else if(sbv instanceof BytesConstantTimeSelect0SuccinctBitVector){ return bytesConstSelect0Sbv((BytesConstantTimeSelect0SuccinctBitVector)sbv); } else if(sbv instanceof LongsSuccinctBitVector){ return longsSbv((LongsSuccinctBitVector)sbv); } else if(sbv instanceof LongsRank1OnlySuccinctBitVector){ return longsRank1Sbv((LongsRank1OnlySuccinctBitVector)sbv); } else if(sbv instanceof LongsConstantTimeSelect0SuccinctBitVector){ return longsConstSelect0Sbv((LongsConstantTimeSelect0SuccinctBitVector)sbv); } else{ throw new RuntimeException(); } } public int cp(String name, BytesSuccinctBitVector sbv){ p.println("%s: %s {", name, sbv.getClass().getSimpleName()); int total = 0; p.nest(); try{ total = cp("bytes", sbv.getBytes()) + cp("rank0Cache", sbv.getCountCache0()) + cp("select0Cache", sbv.getIndexCache0()); } finally{ p.unnest(); } p.println("}; %d.", total); return total; } public int bytesRank1Sbv(BytesRank1OnlySuccinctBitVector sbv){ p.println(sbv.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ int bytes = sbv.getBytes().length; p.println("bytes: byte[]; %d.", bytes); int rank1Caches = sbv.getCountCache1().length * 4; p.println("rank1Cache: int[]; %d.", rank1Caches); total = bytes + rank1Caches; } finally{ p.unnest(); } p.println("}; %d.", total); return total; } public int bytesConstSelect0Sbv(BytesConstantTimeSelect0SuccinctBitVector sbv){ p.println(sbv.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ int bytes = sbv.getBytes().length; p.println("bytes: %d.", bytes); int rank0Caches = sbv.getCountCache0().length * 4; p.println("rank0Cache: %d.", rank0Caches); int bvd = cp("bvD", sbv.getBvD()); int bvr = cp("bvR", sbv.getBvR()); int ars = sbv.getArS().length * 4; p.println("arS: int[]; %d.", ars); total = bytes + rank0Caches + bvd + bvr + ars; } finally{ p.unnest(); } p.println("}; %d.", total); return total; } public int longsSbv(LongsSuccinctBitVector sbv){ p.println(sbv.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ int bytes = sbv.getLongs().length * 8; p.println("longs: long[]; %d.", bytes); int rank0Caches = sbv.getCountCache0().length * 4; p.println("rank0Cache: int[]; %d.", rank0Caches); int select0Caches = sbv.getIndexCache0().size() * 4; p.println("select0Cache: int[]; %d.", select0Caches); total = bytes + rank0Caches + select0Caches; } finally{ p.unnest(); } p.println("} %d.", total); return total; } public int longsRank1Sbv(LongsRank1OnlySuccinctBitVector sbv){ p.println(sbv.getClass().getSimpleName() + " {"); int total = 0; p.nest(); try{ int bytes = sbv.getLongs().length * 8; p.println("longs: long[]; %d.", bytes); int rank1Caches = sbv.getCountCache1().length * 4; p.println("rank1Cache: int[]; %d.", rank1Caches); total = bytes + rank1Caches; } finally{ p.unnest(); } p.println("}; %d.", total); return total; } public int longsConstSelect0Sbv(LongsConstantTimeSelect0SuccinctBitVector sbv){ return startObject(sbv) .cp2("longs", sbv.getLongs()) .cp2("rank0Cache", sbv.getCountCache0()) .cp2("bvD", sbv.getBvD()) .cp2("bvR", sbv.getBvR()) .cp2("arS", sbv.getArS()) .endObject(); } public TrieMemoryUsage startObject(Object value){ p.println(value.getClass().getSimpleName() + " {"); p.nest(); objSizes.push(0); return this; } public TrieMemoryUsage cp2(String name, Object value){ int size = getSize(value); p.println("%s: %s; %d.", name, getTypeName(value.getClass()), size); int i = objSizes.size() - 1; objSizes.set(i, objSizes.get(i) + size); return this; } public int endObject(){ int total = objSizes.pop(); p.unnest(); p.println("}; %d.", total); return total; } private Stack<Integer> objSizes = new Stack<Integer>(); /** * calc and print. * @param name * @param value * @return */ private int cp(String name, Object value){ if(value.getClass().isArray()){ int sz = getSize(value); p.println("%s: %s; %d.", name, getTypeName(value.getClass()), sz); return sz; } else if(value instanceof IntArray){ return cp(name, (IntArray)value); } else{ throw new RuntimeException(); } } private int cp(String name, IntArray value){ int sz = value.getElements().length * 4; p.println("%s: %s; %d.", name, "int[]", sz); return sz; } private String getTypeName(Class<?> clazz){ if(clazz.isPrimitive()){ return typeNames.get(clazz); } else if(clazz.isArray()){ return getTypeName(clazz.getComponentType()) + "[]"; } else{ throw new RuntimeException(); } } private int getSize(Object value){ return getSize(value, value.getClass()); } private int getSize(Object value, Class<?> clazz){ if(clazz.isPrimitive()){ return sizes.get(clazz); } else if(clazz.isArray()){ int len = Array.getLength(value); if(len == 0) return len; return len * getSize(Array.get(value, 0), clazz.getComponentType()); } else{ throw new RuntimeException(); } } private NestAwarePrinter p = new NestAwarePrinter(); private Map<Class<?>, Integer> sizes = new HashMap<Class<?>, Integer>(); private Map<Class<?>, String> typeNames = new HashMap<Class<?>, String>(); { sizes.put(byte.class, 1); sizes.put(char.class, 2); sizes.put(short.class, 2); sizes.put(int.class, 4); sizes.put(long.class, 8); sizes.put(float.class, 4); sizes.put(double.class, 8); typeNames.put(byte.class, "byte"); typeNames.put(char.class, "char"); typeNames.put(short.class, "short"); typeNames.put(int.class, "int"); typeNames.put(long.class, "long"); typeNames.put(float.class, "float"); typeNames.put(double.class, "double"); } }