// Copyright 2017 JanusGraph Authors // // Licensed 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.janusgraph.testutil; import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.HashMultimap; import java.util.*; import java.util.concurrent.*; /** * Measures the approximate size of an object in memory, given a Class which * has a no-argument constructor. */ public final class ObjectSizer { interface Factory { public Object newInstance(); } public static Factory emptyConcurrentHashMap = new Factory() { @Override public Object newInstance() { return fill(new ConcurrentHashMap<Integer, Integer>(5, 0.75f, 2), 20); } }; public static Factory emptyHashMap = new Factory() { @Override public Object newInstance() { return fill(new HashMap<Integer, Integer>(10, 0.75f), 8); } }; public static Factory emptyConcurrentSkipListMap = new Factory() { @Override public Object newInstance() { return fill(new ConcurrentSkipListMap<Integer, Integer>(), 20); } }; public static Factory emptyArrayList = new Factory() { @Override public Object newInstance() { return fill(new ArrayList<Integer>(5), 8); } }; public static Factory emptyArrayQueue = new Factory() { @Override public Object newInstance() { return fill(new ArrayBlockingQueue<Integer>(10), 20); } }; public static Factory emptyMultimap = new Factory() { @Override public Object newInstance() { return fill(HashMultimap.create(5, 1), 5); } }; // public static Factory emptyArrayAdjacency = new Factory() { // @Override // public Object newInstance() { return new ArrayAdjacencyList(); } // }; public static Factory emptyCopyArrayList = new Factory() { @Override public Object newInstance() { return fill(new CopyOnWriteArrayList<Integer>(), 20); } }; public static Factory stringConcurrentSet = new Factory() { @Override public Object newInstance() { ConcurrentSkipListSet<String> set = new ConcurrentSkipListSet<String>(); int size = 100; for (int i = 0; i < size; i++) set.add("String" + i); return set; } }; public static Factory stringConcurrenthashmap = new Factory() { @Override public Object newInstance() { ConcurrentHashMap<String, Boolean> set = new ConcurrentHashMap<String, Boolean>(1, 1); int size = 1000; for (int i = 0; i < size; i++) set.put("String" + i, Boolean.TRUE); return set; } }; public static Factory emptyConcurrentSkipList = new Factory() { @Override public Object newInstance() { ConcurrentSkipListMap<String, String> map = new ConcurrentSkipListMap<String, String>(); return map; } }; public static Factory guavaFactory = new Factory() { @Override public Object newInstance() { int size = 10000; Cache<String,Long> cache = CacheBuilder.newBuilder() .concurrencyLevel(2).initialCapacity(16*3) .maximumSize(10000).build(); // for (int i=0;i<size;i++) { // cache.put(new Nothing(),new Nothing()); // } return cache; } }; private static class Nothing {} public static Map<Integer, Integer> fill(Map<Integer, Integer> m, int size) { for (int i = 0; i < size; i++) m.put(i, i); return m; } public static HashMultimap<Integer, Integer> fill(HashMultimap<Integer, Integer> m, int size) { for (int i = 0; i < size; i++) m.put(i, i); return m; } public static Collection<Integer> fill(Collection<Integer> m, int size) { for (int i = 0; i < size; i++) m.add(i); return m; } /** * First and only argument is the package-qualified name of a class * which has a no-argument constructor. */ public static void main(String... aArguments) { Factory theClass = null; try { theClass = guavaFactory; } catch (Exception ex) { System.err.println("Cannot build a Class object: " + aArguments[0]); System.err.println("Use a package-qualified name, and check classpath."); } long size = ObjectSizer.getObjectSize(theClass); System.out.println("Approximate size of " + theClass + " objects :" + size); } /** * Return the approximate size in bytes, and return zero if the class * has no default constructor. */ public static long getObjectSize(Factory factory) { long result = 0; //this array will simply hold a bunch of references, such that //the objects cannot be garbage-collected Object[] objects = new Object[SAMPLE_SIZE]; MemoryAssess mem = new MemoryAssess(); //build a bunch of identical objects try { Object throwAway = factory.newInstance(); mem.start(); for (int idx = 0; idx < objects.length; ++idx) { objects[idx] = factory.newInstance(); } double approximateSize = (mem.end() - 12 - SAMPLE_SIZE*OBJECT_POINTER_SIZE) * 1.0 / SAMPLE_SIZE; result = Math.round(approximateSize); } catch (Exception ex) { System.err.println("Cannot create object using " + factory); } return result; } // PRIVATE // private static int SAMPLE_SIZE = 100; private static int OBJECT_POINTER_SIZE = 6; //assuming compressed pointers }