All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.gridkit.jvmtool.heapdump.HeapHistogram Maven / Gradle / Ivy

There is a newer version: 0.16
Show newest version
/**
 * Copyright 2014 Alexey Ragozin
 *
 * 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.gridkit.jvmtool.heapdump;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.netbeans.lib.profiler.heap.Instance;

public class HeapHistogram implements InstanceCallback {

    public static final Comparator BY_NAME = new Comparator() {

        @Override
        public int compare(ClassRecord o1, ClassRecord o2) {
            return o1.className.compareTo(o2.className);
        }

        public String toString() {
            return "BY_NAME";
        }
    };

    public static final Comparator BY_SIZE = new Comparator() {

        @Override
        public int compare(ClassRecord o1, ClassRecord o2) {
            return Long.valueOf(o2.totalSize).compareTo(o1.totalSize);
        }

        public String toString() {
            return "BY_SIZE";
        }
    };

    public static final Comparator BY_COUNT = new Comparator() {

        @Override
        public int compare(ClassRecord o1, ClassRecord o2) {
            return Long.valueOf(o2.instanceCount).compareTo(o1.instanceCount);
        }

        public String toString() {
            return "BY_COUNT";
        }
    };

    private Map classes = new HashMap();
    private ClassRecord total = new ClassRecord("Total heap");
    private RefSet known = null;

    public void enableInstanceTracking() {
        if (known == null) {
            known = new RefSet();
        }
    }

    @Override
    public void feed(Instance instance) {
        accumulate(instance);
    }

    public void accumulate(Instance i) {
        if (known != null) {
            if (known.getAndSet(i.getInstanceId(), true)) {
                // already accumulated
                return;
            }
        }
        total.add(i);
        String cn = i.getJavaClass().getName();
        ClassRecord cr = classes.get(cn);
        if (cr == null) {
            cr = new ClassRecord(cn);
            classes.put(cn, cr);
        }
        ++cr.instanceCount;
        cr.totalSize += i.getSize();
    }

    public long getTotalCount() {
        return total.getInstanceCount();
    }

    public long getTotalSize() {
        return total.getTotalSize();
    }

    public ClassRecord getClassInfo(String type) {
        return classes.get(type);
    }

    public Collection getHisto() {
        return classes.values();
    }

    public Collection getHistoByName() {
        List histo = new ArrayList(classes.values());
        Collections.sort(histo, BY_NAME);
        return histo;
    }

    public Collection getHistoBySize() {
        List histo = new ArrayList(classes.values());
        Collections.sort(histo, BY_SIZE);
        return histo;
    }

    public static class ClassRecord {

        String className;
        long instanceCount;
        long totalSize;

        public ClassRecord(String name) {
            className = name;
        }

        void add(Instance i) {
            ++instanceCount;
            totalSize += i.getSize();
        }

        public String getClassName() {
            return className;
        }

        public long getInstanceCount() {
            return instanceCount;
        }

        public long getTotalSize() {
            return totalSize;
        }

        public String toString() {
            return className + " " + toMemorySize(totalSize) + "(" + instanceCount + ")";
        }
    }

    private static final String toMemorySize(long n) {
        if (n < (10l << 10)) {
            return String.valueOf(n);
        }
        else if (n < (10l << 20)) {
            return String.valueOf(n >> 10) + "k";
        }
        else if (n < (10l << 30)) {
            return String.valueOf(n >> 20) + "m";
        }
        else {
            return String.valueOf(n >> 30) + "g";
        }
    }

    public String formatTop(int top) {
        TextTable table = new TextTable();
        table.addRow("", "Size", " Count", " Type");
        int n = 0;
        for(ClassRecord cr: getHistoBySize()) {
            ++n;
            table.addRow("" + n, " " + cr.getTotalSize(), " " + cr.getInstanceCount(), " " + cr.getClassName());
            if (n == top) {
                break;
            }
        }
        table.addRow("TOTAL", " " + total.totalSize, " " + total.instanceCount, "");
        return table.formatTextTableUnbordered(180);
    }

    @Override
    public String toString() {
        TextTable table = new TextTable();
        table.addRow("", "Size", " Count", " Type");
        int n = 0;
        for(ClassRecord cr: getHistoBySize()) {
            table.addRow("" + n, " " + cr.getTotalSize(), " " + cr.getInstanceCount(), " " + cr.getClassName());
            ++n;
        }
        table.addRow("TOTAL", " " + total.totalSize, " " + total.instanceCount, "");
        return table.formatTextTableUnbordered(180);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy