Package net.luminis.jmx.topthreads

Source Code of net.luminis.jmx.topthreads.DiffStackTraces

/*
* Copyright 2007-2013 Peter Doornbosch
*
* This file is part of TopThreads, a JConsole plugin to analyse CPU-usage per thread.
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser General Public License
* (LGPL) version 2.1 which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/lgpl-2.1.html
*
* TopThreads is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*/
package net.luminis.jmx.topthreads;

import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextPane;
import javax.swing.text.AttributeSet;
import javax.swing.text.BadLocationException;
import javax.swing.text.DefaultStyledDocument;
import javax.swing.text.SimpleAttributeSet;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;
import java.awt.Color;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class DiffStackTraces
{
    private List<String> st1;
    private List<String> st2;

    public DiffStackTraces(List<String> st1, List<String> st2) {
        this.st1 = st1;
        this.st2 = st2;
    }

    public DiffStackTraces(String[] st1, String[] st2) {
        this.st1 = Arrays.asList(st1);
        this.st2 = Arrays.asList(st2);
    }

    public DiffStackTraces(StackTraceElement[] st1, StackTraceElement[] st2) {
        this.st1 = new ArrayList<String>();
        for (StackTraceElement el: st1) {
            this.st1.add(el.toString());
        }
        this.st2 = new ArrayList<String>();
        for (StackTraceElement el: st2) {
            this.st2.add(el.toString());
        }
    }

    private List matches = new ArrayList();

    public DiffStackTraces diff() {

        boolean tryDown = false;

        for (int index = st2.size() - 1; index >= 0; index--) {
            String line = st2.get(index);

            Integer firstMatch = null;
            Integer lastMatch = null;
            for (int search = st1.size() -1; search >= 0; search--) {
                if (firstMatch == null) {
                    if (st1.get(search).equals(line)) {
                        firstMatch = search;
                        lastMatch = search;
                    }
                }
                else {
                    // st1[firstMatch] equals st2[index]
                    int inspect = index + (search - firstMatch);
                    if (inspect >= 0 && st1.get(search).equals(st2.get(inspect))) {
                        lastMatch = search;
                    }
                    else {
                        break;
                    }
                }
            }

            int growDown = 0;
            // A second match starts where that last one failed, otherwise we get many overlapping matches, e.g.
            // 'baaab' and 'baab' matches 'aab', 'aa' (twice) and 'a' (six times). Of course, we could remove such
            // overlapping matches, but...
            // This solution is easier and cheaper:
            // - if the next match is adjacent to the previous
            // - try whether this match can be extended ("grow down", because we work bottom up)
            if (tryDown && firstMatch != null) {
                int start = firstMatch;
                while (start + 1 + growDown < st1.size() && index + 1 + growDown < st2.size()) {
                    if (st1.get(start + 1 + growDown).equals(st2.get(index + 1 + growDown))) {
                        firstMatch = start + 1 + growDown;
                        growDown++;
                    }
                    else
                        break;
                }
                if (growDown > 0) {
                    //System.out.println("match grown down with " + (growDown-1));
                }
            }

            if (firstMatch != null) {
                int size = firstMatch - lastMatch + 1;
                if (size > 1) {
                    matches.add(new Object[] { new int[] { lastMatch, firstMatch }, new int[] { index + growDown - size + 1, index + growDown } });
                    //System.out.println("got a match from " + lastMatch + ":" + firstMatch + "->" + (index + growDown - size + 1) + ":" + (index + growDown) + ", size=" + size);
                }
                else {
                    //System.out.println("neglecting single line match from " + lastMatch + ":" + firstMatch + "->" + (index - size + 1) + ":" + index + ", size=" + size);
                }

                // Continue search from first non-matching line
                index = index - size + 1;    // Add one, because the for loop decrements before entering the next loop

                // Because the previous line makes us skip overlapping matches, we need to try to "grow down" the next match
                tryDown = true;
            }
        }

        return this;
    }

    public int getNrOfMatches() {
        return matches.size();
    }

    public Object[] getMatch(int index) {
        return (Object[]) matches.get(index);
    }

    public int[] getMatchFrom(int index) {
        return (int[]) ((Object[]) matches.get(index))[0];
    }

    public int[] getMatchTo(int index) {
        return (int[]) ((Object[]) matches.get(index))[1];
    }

    public Object[] largestMatch() {

        int max = 0;
        Object[] largest = null;

        for (Object m: matches) {
            int[] range = (int[]) ((Object[]) m)[0];
            int size = range[1] - range[0];
            if (size > max) {
                max = size;
                largest = (Object[]) m;
            }
        }
        return (Object[]) largest;
    }

    public void visualize() throws BadLocationException {
        JFrame frame = new JFrame();
        JPanel contentPane = new JPanel();
        contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.X_AXIS));
        JTextPane left = new JTextPane();
        JTextPane right = new JTextPane();
        contentPane.add(left);
        contentPane.add(right);
        Object[] match = largestMatch();
        int[] rangeLeft = (int[]) match[0];
        int[] range = (int[]) match[1];

        StyledDocument document = new DefaultStyledDocument();
        SimpleAttributeSet colorAttrs = new SimpleAttributeSet();
        colorAttrs.addAttribute(StyleConstants.Background, Color.lightGray);

        SimpleAttributeSet italics = new SimpleAttributeSet();
        italics.addAttribute(StyleConstants.Italic, true);

        SimpleAttributeSet fontColor = new SimpleAttributeSet();
        fontColor.addAttribute(StyleConstants.Foreground, Color.red);

        AttributeSet defaultAttrs = new SimpleAttributeSet();

        int index = 0;
        for (String s: st1) {
            if (index >= rangeLeft[0] && index <= rangeLeft[1])
                document.insertString(document.getLength(), s + "\n", fontColor);
            else {
                document.insertString(document.getLength(), s + "\n", defaultAttrs);
            }
            index++;
        }
        left.setDocument(document);

        document = new DefaultStyledDocument();
        index = 0;
        for (String s: st2) {
            if (index >= range[0] && index <= range[1])
                document.insertString(document.getLength(), s + "\n", colorAttrs);
            else {
                document.insertString(document.getLength(), s + "\n", defaultAttrs);
            }
            index++;
        }
        right.setDocument(document);

        JScrollPane scroller = new JScrollPane(contentPane);

        frame.getContentPane().add(scroller);
        frame.pack();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);
    }

    public static void main(String[] args) throws Exception {
        BufferedReader in = new BufferedReader(new FileReader(args[0]));
        String line;
        List<String> st1 = new ArrayList();
        while ((line = in.readLine()) != null) {
            st1.add(line);
        }
        in.close();

        in = new BufferedReader(new FileReader(args[1]));
        List<String> st2 = new ArrayList();
        while ((line = in.readLine()) != null) {
            st2.add(line);
        }
        in.close();

        new DiffStackTraces(st1, st2).diff().visualize();
    }
}
TOP

Related Classes of net.luminis.jmx.topthreads.DiffStackTraces

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.