001/* 002 * jPOS Project [http://jpos.org] 003 * Copyright (C) 2000-2026 jPOS Software SRL 004 * 005 * This program is free software: you can redistribute it and/or modify 006 * it under the terms of the GNU Affero General Public License as 007 * published by the Free Software Foundation, either version 3 of the 008 * License, or (at your option) any later version. 009 * 010 * This program is distributed in the hope that it will be useful, 011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 013 * GNU Affero General Public License for more details. 014 * 015 * You should have received a copy of the GNU Affero General Public License 016 * along with this program. If not, see <http://www.gnu.org/licenses/>. 017 */ 018 019package org.jpos.util; 020 021import org.jpos.iso.ISOUtil; 022 023import java.io.PrintStream; 024import java.util.Collection; 025import java.util.Iterator; 026import java.util.LinkedHashMap; 027 028/** 029 * Simple Profiler 030 * @author Alejandro P. Revilla 031 * @author David D. Bergert 032 * @version $Id$ 033 */ 034public class Profiler implements Loggeable { 035 long start, partial; 036 LinkedHashMap<String, Entry> events; 037 public static final int TO_MILLIS = 1000000; 038 039 public Profiler () { 040 super(); 041 reset(); 042 } 043 /** 044 * reset timers 045 */ 046 public void reset() { 047 start = partial = System.nanoTime(); 048 events = new LinkedHashMap<>(); 049 } 050 /** 051 * mark checkpoint 052 * @param detail checkpoint information 053 */ 054 @SuppressWarnings("unchecked") 055 public synchronized void checkPoint (String detail) { 056 long now = System.nanoTime(); 057 Entry e = new Entry(); 058 e.setDurationInNanos(now - partial); 059 e.setTotalDurationInNanos(now - start); 060 if (events.containsKey(detail)) { 061 for (int i=1; ;i++) { 062 String d = detail + "-" + i; 063 if (!events.containsKey (d)) { 064 detail = d; 065 break; 066 } 067 } 068 } 069 e.setEventName(detail); 070 events.put (detail, e); 071 partial = now; 072 } 073 /** 074 * @return total elapsed time since last reset 075 */ 076 public long getElapsed() { 077 return System.nanoTime() - start; 078 } 079 public long getElapsedInMillis() { 080 return getElapsed() / TO_MILLIS; 081 } 082 /** 083 * @return parcial elapsed time since last reset 084 */ 085 public long getPartial() { 086 return System.nanoTime() - partial; 087 } 088 public long getPartialInMillis() { 089 return getPartial() / TO_MILLIS; 090 } 091 public void dump (PrintStream p, String indent) { 092 String inner = indent + " "; 093 if (!events.containsKey("end")) 094 checkPoint ("end"); 095 Collection c = events.values(); 096 Iterator iter = c.iterator(); 097 p.println (indent + "<profiler>"); 098 while (iter.hasNext()) 099 p.println (inner + ISOUtil.normalize(iter.next().toString())); 100 p.println (indent + "</profiler>"); 101 } 102 public LinkedHashMap<String, Entry> getEvents() { 103 return events; 104 } 105 public Entry getEntry(String eventName) { 106 return events.get(eventName); 107 } 108 public void reenable() { 109 events.remove("end"); 110 } 111 public static class Entry { 112 String eventName; 113 long duration; 114 long totalDuration; 115 public Entry() { 116 eventName = ""; 117 duration = 0L; 118 totalDuration = 0L; 119 } 120 public void setEventName (String myEvent) { 121 this.eventName = myEvent; 122 } 123 public String getEventName () { 124 return eventName; 125 } 126 public void setDurationInNanos (long duration) { 127 this.duration = duration; 128 } 129 public long getDuration () { 130 return duration / TO_MILLIS; 131 } 132 public long getDurationInNanos() { 133 return duration; 134 } 135 public void setTotalDurationInNanos (long totalDuration) { 136 this.totalDuration = totalDuration; 137 } 138 public long getTotalDuration () { 139 return totalDuration / TO_MILLIS; 140 } 141 public long getTotalDurationInNanos () { 142 return totalDuration; 143 } 144 public String toString() { 145 StringBuilder sb = new StringBuilder (eventName); 146 sb.append (" ["); 147 sb.append (getDuration()); 148 sb.append ('.'); 149 sb.append (duration % TO_MILLIS / 100000); 150 sb.append ('/'); 151 sb.append (getTotalDuration ()); 152 sb.append ('.'); 153 sb.append (totalDuration % TO_MILLIS / 100000); 154 sb.append (']'); 155 return sb.toString(); 156 } 157 } 158}