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

com.alipay.rdf.file.util.RdfProfiler Maven / Gradle / Ivy

There is a newer version: 2.2.11
Show newest version
package com.alipay.rdf.file.util;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

/**
 * Copyright (C) 2013-2018 Ant Financial Services Group
 * 
 * 用来测试并统计线程执行时间的工具。
 * 
 * @author hongwei.quhw
 * @version $Id: Profiler.java, v 0.1 2017年5月9日 下午3:47:28 hongwei.quhw Exp $
 */
@SuppressWarnings({ "unchecked", "rawtypes" })
public class RdfProfiler {
    private static final ThreadLocal entryStack = new ThreadLocal();

    /**
     * 开始计时。
     *
     * @param message 第一个entry的信息
     */
    public static void start(String message) {
        entryStack.set(new Entry(message, null, null));
    }

    /**
     * 清除计时器。
     * 
     * 

* 清除以后必须再次调用start方可重新计时。 *

*/ public static void reset() { entryStack.set(null); } /** * 开始一个新的entry,并计时。 * * @param message 新entry的信息 */ public static void enter(String message) { Entry currentEntry = getCurrentEntry(); if (currentEntry != null) { currentEntry.enterSubEntry(message); } } /** * 结束最近的一个entry,记录结束时间。 */ public static void release() { release(null); } /** * 结束最近的一个entry,记录结束时间。 */ public static void release(String message) { Entry currentEntry = getCurrentEntry(); if (currentEntry != null) { currentEntry.release(message); } } /** * 取得耗费的总时间。 * * @return 耗费的总时间,如果未开始计时,则返回-1 */ public static long getDuration() { Entry entry = (Entry) entryStack.get(); if (entry != null) { return entry.getDuration(); } else { return -1; } } /** * 列出所有的entry。 * * @return 列出所有entry,并统计各自所占用的时间 */ public static String dump() { return dump("", ""); } /** * 列出所有的entry。 * * @param prefix 前缀 * * @return 列出所有entry,并统计各自所占用的时间 */ public static String dump(String prefix) { return dump(prefix, prefix); } /** * 列出所有的entry。 * * @param prefix1 首行前缀 * @param prefix2 后续行前缀 * * @return 列出所有entry,并统计各自所占用的时间 */ public static String dump(String prefix1, String prefix2) { Entry entry = (Entry) entryStack.get(); if (entry != null) { return entry.toString(prefix1, prefix2); } else { return ""; } } /** * 取得第一个entry。 * * @return 第一个entry,如果不存在,则返回null */ public static Entry getEntry() { return (Entry) entryStack.get(); } /** * 取得最近的一个entry。 * * @return 最近的一个entry,如果不存在,则返回null */ private static Entry getCurrentEntry() { Entry subEntry = (Entry) entryStack.get(); Entry entry = null; if (subEntry != null) { do { entry = subEntry; subEntry = entry.getUnreleasedEntry(); } while (subEntry != null); } return entry; } /** * 代表一个计时单元。 */ public static final class Entry { private final List subEntries = new ArrayList(4); private final String key; private final Entry parentEntry; private final Entry firstEntry; private final long baseTime; private final long startTime; private String message; private long endTime; /** * 创建一个新的entry。 * * @param message entry的信息,可以是null * @param parentEntry 父entry,可以是null * @param firstEntry 第一个entry,可以是null */ private Entry(String key, Entry parentEntry, Entry firstEntry) { this.key = key; this.startTime = System.currentTimeMillis(); this.parentEntry = parentEntry; this.firstEntry = (Entry) ((firstEntry != null) ? firstEntry : this); this.baseTime = (firstEntry == null) ? 0 : firstEntry.startTime; } /** * 取得entry相对于第一个entry的起始时间。 * * @return 相对起始时间 */ public long getStartTime() { return (baseTime > 0) ? (startTime - baseTime) : 0; } /** * 取得entry相对于第一个entry的结束时间。 * * @return 相对结束时间,如果entry还未结束,则返回-1 */ public long getEndTime() { if (endTime < baseTime) { return -1; } else { return endTime - baseTime; } } /** * 取得entry持续的时间。 * * @return entry持续的时间,如果entry还未结束,则返回-1 */ public long getDuration() { if (endTime < startTime) { return -1; } else { return endTime - startTime; } } /** * 取得entry自身所用的时间,即总时间减去所有子entry所用的时间。 * * @return entry自身所用的时间,如果entry还未结束,则返回-1 */ public long getDurationOfSelf() { long duration = getDuration(); if (duration < 0) { return -1; } else if (subEntries.isEmpty()) { return duration; } else { for (int i = 0; i < subEntries.size(); i++) { Entry subEntry = (Entry) subEntries.get(i); duration -= subEntry.getDuration(); } if (duration < 0) { return -1; } else { return duration; } } } /** * 取得当前entry在父entry中所占的时间百分比。 * * @return 百分比 */ public double getPecentage() { double parentDuration = 0; double duration = getDuration(); if ((parentEntry != null) && parentEntry.isReleased()) { parentDuration = parentEntry.getDuration(); } if ((duration > 0) && (parentDuration > 0)) { return duration / parentDuration; } else { return 0; } } /** * 取得当前entry在第一个entry中所占的时间百分比。 * * @return 百分比 */ public double getPecentageOfAll() { double firstDuration = 0; double duration = getDuration(); if ((firstEntry != null) && firstEntry.isReleased()) { firstDuration = firstEntry.getDuration(); } if ((duration > 0) && (firstDuration > 0)) { return duration / firstDuration; } else { return 0; } } /** * 取得所有子entries。 * * @return 所有子entries的列表(不可更改) */ public List getSubEntries() { return Collections.unmodifiableList(subEntries); } /** * 结束当前entry,并记录结束时间。 */ private void release(String message) { endTime = System.currentTimeMillis(); this.message = message; } /** * 判断当前entry是否结束。 * * @return 如果entry已经结束,则返回true */ private boolean isReleased() { return endTime > 0; } /** * 创建一个新的子entry。 * * @param message 子entry的信息 */ private void enterSubEntry(String message) { Entry subEntry = new Entry(message, this, firstEntry); subEntries.add(subEntry); } /** * 取得未结束的子entry。 * * @return 未结束的子entry,如果没有子entry,或所有entry均已结束,则返回null */ private Entry getUnreleasedEntry() { Entry subEntry = null; if (!subEntries.isEmpty()) { subEntry = (Entry) subEntries.get(subEntries.size() - 1); if (subEntry.isReleased()) { subEntry = null; } } return subEntry; } /** * 将entry转换成字符串的表示。 * * @return 字符串表示的entry */ public String toString() { return toString("", ""); } /** * 将entry转换成字符串的表示。 * * @param prefix1 首行前缀 * @param prefix2 后续行前缀 * * @return 字符串表示的entry */ private String toString(String prefix1, String prefix2) { StringBuffer buffer = new StringBuffer(); toString(buffer, prefix1, prefix2); return buffer.toString(); } private String getMessage() { if (RdfFileUtil.isNotBlank(message)) { return key + "[" + message + "]"; } return key; } /** * 将entry转换成字符串的表示。 * * @param buffer 字符串buffer * @param prefix1 首行前缀 * @param prefix2 后续行前缀 */ private void toString(StringBuffer buffer, String prefix1, String prefix2) { buffer.append(prefix1); long startTime = getStartTime(); long duration = getDuration(); long durationOfSelf = getDurationOfSelf(); double percent = getPecentage(); double percentOfAll = getPecentageOfAll(); Object[] params = new Object[] { getMessage(), // {0} - entry信息 new Long(startTime), // {1} - 起始时间 new Long(duration), // {2} - 持续总时间 new Long(durationOfSelf), // {3} - 自身消耗的时间 new Double(percent), // {4} - 在父entry中所占的时间比例 new Double(percentOfAll) // {5} - 在总时间中所旧的时间比例 }; StringBuffer pattern = new StringBuffer("{1,number} "); if (isReleased()) { pattern.append("[{2,number}ms"); if ((durationOfSelf > 0) && (durationOfSelf != duration)) { pattern.append(" ({3,number}ms)"); } if (percent > 0) { pattern.append(", {4,number,##%}"); } if (percentOfAll > 0) { pattern.append(", {5,number,##%}"); } pattern.append("]"); } else { pattern.append("[UNRELEASED]"); } pattern.append(" - {0}"); buffer.append(MessageFormat.format(pattern.toString(), params)); for (int i = 0; i < subEntries.size(); i++) { Entry subEntry = (Entry) subEntries.get(i); buffer.append('\n'); if (i == (subEntries.size() - 1)) { subEntry.toString(buffer, prefix2 + "`---", prefix2 + " "); // 最后一项 } else if (i == 0) { subEntry.toString(buffer, prefix2 + "+---", prefix2 + "| "); // 第一项 } else { subEntry.toString(buffer, prefix2 + "+---", prefix2 + "| "); // 中间项 } } } } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy