Search in sources :

Example 1 with ToLongFunction

use of java.util.function.ToLongFunction in project lucene-solr by apache.

the class RamUsageTester method measureObjectSize.

/*
   * Non-recursive version of object descend. This consumes more memory than recursive in-depth
   * traversal but prevents stack overflows on long chains of objects
   * or complex graphs (a max. recursion depth on my machine was ~5000 objects linked in a chain
   * so not too much).
   */
private static long measureObjectSize(Object root, Accumulator accumulator) {
    // Objects seen so far.
    final Set<Object> seen = Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>());
    // Class cache with reference Field and precalculated shallow size. 
    final IdentityHashMap<Class<?>, ClassCache> classCache = new IdentityHashMap<>();
    // Stack of objects pending traversal. Recursion caused stack overflows. 
    final ArrayList<Object> stack = new ArrayList<>();
    stack.add(root);
    long totalSize = 0;
    while (!stack.isEmpty()) {
        final Object ob = stack.remove(stack.size() - 1);
        if (ob == null || seen.contains(ob)) {
            continue;
        }
        seen.add(ob);
        final Class<?> obClazz = ob.getClass();
        assert obClazz != null : "jvm bug detected (Object.getClass() == null). please report this to your vendor";
        if (obClazz.isArray()) {
            /*
         * Consider an array, possibly of primitive types. Push any of its references to
         * the processing stack and accumulate this array's shallow size. 
         */
            final long shallowSize = RamUsageEstimator.shallowSizeOf(ob);
            final int len = Array.getLength(ob);
            final List<Object> values;
            Class<?> componentClazz = obClazz.getComponentType();
            if (componentClazz.isPrimitive()) {
                values = Collections.emptyList();
            } else {
                values = new AbstractList<Object>() {

                    @Override
                    public Object get(int index) {
                        return Array.get(ob, index);
                    }

                    @Override
                    public int size() {
                        return len;
                    }
                };
            }
            totalSize += accumulator.accumulateArray(ob, shallowSize, values, stack);
        } else {
            /*
         * Consider an object. Push any references it has to the processing stack
         * and accumulate this object's shallow size. 
         */
            try {
                ClassCache cachedInfo = classCache.get(obClazz);
                if (cachedInfo == null) {
                    classCache.put(obClazz, cachedInfo = createCacheEntry(obClazz));
                }
                boolean needsReflection = true;
                if (Constants.JRE_IS_MINIMUM_JAVA9 && obClazz.getName().startsWith("java.")) {
                    // Java 9: Best guess for some known types, as we cannot precisely look into runtime classes:
                    final ToLongFunction<Object> func = SIMPLE_TYPES.get(obClazz);
                    if (func != null) {
                        // some simple type like String where the size is easy to get from public properties
                        totalSize += accumulator.accumulateObject(ob, cachedInfo.alignedShallowInstanceSize + func.applyAsLong(ob), Collections.emptyMap(), stack);
                        needsReflection = false;
                    } else if (ob instanceof Iterable) {
                        final List<Object> values = StreamSupport.stream(((Iterable<?>) ob).spliterator(), false).collect(Collectors.toList());
                        totalSize += accumulator.accumulateArray(ob, cachedInfo.alignedShallowInstanceSize + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER, values, stack);
                        needsReflection = false;
                    } else if (ob instanceof Map) {
                        final List<Object> values = ((Map<?, ?>) ob).entrySet().stream().flatMap(e -> Stream.of(e.getKey(), e.getValue())).collect(Collectors.toList());
                        totalSize += accumulator.accumulateArray(ob, cachedInfo.alignedShallowInstanceSize + RamUsageEstimator.NUM_BYTES_ARRAY_HEADER, values, stack);
                        totalSize += RamUsageEstimator.NUM_BYTES_ARRAY_HEADER;
                        needsReflection = false;
                    }
                }
                if (needsReflection) {
                    final Map<Field, Object> fieldValues = new HashMap<>();
                    for (Field f : cachedInfo.referenceFields) {
                        fieldValues.put(f, f.get(ob));
                    }
                    totalSize += accumulator.accumulateObject(ob, cachedInfo.alignedShallowInstanceSize, fieldValues, stack);
                }
            } catch (IllegalAccessException e) {
                // this should never happen as we enabled setAccessible().
                throw new RuntimeException("Reflective field access failed?", e);
            }
        }
    }
    // Help the GC (?).
    seen.clear();
    stack.clear();
    classCache.clear();
    return totalSize;
}
Also used : Array(java.lang.reflect.Array) IdentityHashMap(java.util.IdentityHashMap) ByteArrayOutputStream(java.io.ByteArrayOutputStream) Collection(java.util.Collection) AbstractList(java.util.AbstractList) Set(java.util.Set) HashMap(java.util.HashMap) Field(java.lang.reflect.Field) PrivilegedAction(java.security.PrivilegedAction) Collectors(java.util.stream.Collectors) File(java.io.File) ArrayList(java.util.ArrayList) List(java.util.List) Stream(java.util.stream.Stream) Modifier(java.lang.reflect.Modifier) Map(java.util.Map) StreamSupport(java.util.stream.StreamSupport) AccessController(java.security.AccessController) ToLongFunction(java.util.function.ToLongFunction) Path(java.nio.file.Path) Collections(java.util.Collections) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) Field(java.lang.reflect.Field) AbstractList(java.util.AbstractList) ArrayList(java.util.ArrayList) List(java.util.List) IdentityHashMap(java.util.IdentityHashMap) HashMap(java.util.HashMap) Map(java.util.Map)

Aggregations

ByteArrayOutputStream (java.io.ByteArrayOutputStream)1 File (java.io.File)1 Array (java.lang.reflect.Array)1 Field (java.lang.reflect.Field)1 Modifier (java.lang.reflect.Modifier)1 Path (java.nio.file.Path)1 AccessController (java.security.AccessController)1 PrivilegedAction (java.security.PrivilegedAction)1 AbstractList (java.util.AbstractList)1 ArrayList (java.util.ArrayList)1 Collection (java.util.Collection)1 Collections (java.util.Collections)1 HashMap (java.util.HashMap)1 IdentityHashMap (java.util.IdentityHashMap)1 List (java.util.List)1 Map (java.util.Map)1 Set (java.util.Set)1 ToLongFunction (java.util.function.ToLongFunction)1 Collectors (java.util.stream.Collectors)1 Stream (java.util.stream.Stream)1