[slf4j-dev] svn commit: r1069 - in slf4j/trunk: . slf4j-ext slf4j-ext/src slf4j-ext/src/main slf4j-ext/src/main/java slf4j-ext/src/main/java/org slf4j-ext/src/main/java/org/slf4j slf4j-ext/src/main/java/org/slf4j/profiler slf4j-ext/src/test slf4j-ext/src/test/java slf4j-ext/src/test/java/org slf4j-ext/src/test/java/org/slf4j slf4j-ext/src/test/java/org/slf4j/profiler

ceki at slf4j.org ceki at slf4j.org
Mon Jul 21 16:28:30 CEST 2008


Author: ceki
Date: Mon Jul 21 16:28:29 2008
New Revision: 1069

Added:
   slf4j/trunk/slf4j-ext/
   slf4j/trunk/slf4j-ext/pom.xml
   slf4j/trunk/slf4j-ext/src/
   slf4j/trunk/slf4j-ext/src/main/
   slf4j/trunk/slf4j-ext/src/main/java/
   slf4j/trunk/slf4j-ext/src/main/java/org/
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/DurationUnit.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Profiler.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/ProfilerRegistry.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/SpacePadder.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/StopWatch.java
   slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Util.java
   slf4j/trunk/slf4j-ext/src/test/
   slf4j/trunk/slf4j-ext/src/test/java/
   slf4j/trunk/slf4j-ext/src/test/java/org/
   slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/
   slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/
   slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/PackageTest.java
   slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/ProfilerTest.java
   slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/StopWatchTest.java
Modified:
   slf4j/trunk/pom.xml

Log:
Related to bug 68. See also [1]

- As suggested by Ralph Goers on comment #5, migrating code from the
logback project, in particular the ch.qos.logback.classic.stopwatch
package to SLF4J. Since 99.9% of the code is logging system
independent, it makes sense to migrate this code to SLF4J, more
precisely into the newly created slf4j-ext module.

The profiler code has been extremely useful in measuring the
performance of a real-world project. 

Documentation to follow.

[1] http://bugzilla.slf4j.org/show_bug.cgi?id=86


Modified: slf4j/trunk/pom.xml
==============================================================================
--- slf4j/trunk/pom.xml	(original)
+++ slf4j/trunk/pom.xml	Mon Jul 21 16:28:29 2008
@@ -30,6 +30,7 @@
 		<module>slf4j-jdk14</module>
     <module>slf4j-log4j12</module>
     <module>slf4j-jcl</module>
+    <module>slf4j-ext</module>
     <module>jcl-over-slf4j</module>
     <module>jcl104-over-slf4j</module>
     <module>log4j-over-slf4j</module>

Added: slf4j/trunk/slf4j-ext/pom.xml
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/pom.xml	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,95 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+  <parent>
+    <groupId>org.slf4j</groupId>
+    <artifactId>slf4j-parent</artifactId>
+    <version>1.5.3-SNAPSHOT</version>
+  </parent>
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <groupId>org.slf4j</groupId>
+  <artifactId>slf4j-ext</artifactId>
+  <packaging>jar</packaging>
+  <name>SLF4J Extensions Module</name>
+
+  <url>http://www.slf4j.org</url>
+  <description>Extensions to the SLF4J API</description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+		</dependency>
+  </dependencies>
+
+
+  <build>
+    <plugins>		
+     
+ 
+		</plugins>
+	</build>
+
+
+  <build>
+
+		<plugins>
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-compiler-plugin</artifactId>
+				<configuration>
+					<source>1.5</source>
+					<target>1.5</target>
+				</configuration>
+			</plugin>
+
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration>
+          <forkMode>once</forkMode>
+          <reportFormat>plain</reportFormat>
+          <trimStackTrace>false</trimStackTrace>
+          <excludes>
+            <exclude>**/AllTest.java</exclude>
+            <exclude>**/PackageTest.java</exclude>
+          </excludes>
+        </configuration>
+      </plugin>
+
+
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-jar-plugin</artifactId>
+        <configuration>
+          <archive>
+            <manifestEntries>
+              <Bundle-Version>${project.version}</Bundle-Version>
+              <Bundle-Description>${project.description}</Bundle-Description>
+              <Implementation-Version>${project.version}</Implementation-Version>
+            </manifestEntries>
+            <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
+          </archive>
+        </configuration>			
+      </plugin>      
+    </plugins>
+
+  </build>
+
+  <reporting>
+    <plugins>
+      <plugin>
+        <groupId>org.codehaus.mojo</groupId>
+        <artifactId>clirr-maven-plugin</artifactId>
+        <configuration>
+          <comparisonVersion>1.5.0</comparisonVersion>
+        </configuration>
+      </plugin>
+    </plugins>
+  </reporting>
+
+</project>
\ No newline at end of file

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/DurationUnit.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/DurationUnit.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,29 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+public enum DurationUnit {
+  NANOSECOND, MICROSECOND, MILLISSECOND, SECOND;
+}
\ No newline at end of file

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Profiler.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Profiler.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,197 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+package org.slf4j.profiler;
+
+import java.util.ArrayList;
+import java.util.List;
+
+
+// +  Profiler [BAS]
+// |-- elapsed time            [doX]     0 milliseconds.
+// |-- elapsed time        [doYYYYY]    56 milliseconds.
+// |--+ Profiler Y
+//    |-- elapsed time            [doZ]    21 milliseconds.
+//    |-- elapsed time            [doZ]    21 milliseconds.
+//    |-- Total elapsed time        [Y]    78 milliseconds.
+// |-- elapsed time            [doZ]    21 milliseconds.
+// |-- Total elapsed time      [BAS]    78 milliseconds.
+
+// + Profiler [TOP]
+// |--+ Profiler [IIII]
+//    |-- elapsed time                            [A]   0.006 milliseconds.
+//    |-- elapsed time                            [B]  75.777 milliseconds.
+//    |-- elapsed time                       [VVVVVV] 161.589 milliseconds.
+//    |-- Total elapsed time                   [IIII] 240.580 milliseconds.
+// |--+ Profiler [RRRRRRRRR]
+//    |-- elapsed time                           [R0]   9.390 milliseconds.
+//    |-- elapsed time                           [R1]   6.555 milliseconds.
+//    |-- elapsed time                           [R2]   5.995 milliseconds.
+//    |-- elapsed time                           [R3] 115.502 milliseconds.
+//    |-- elapsed time                           [R4]   0.064 milliseconds.
+//    |-- Total elapsed time                      [R] 138.340 milliseconds.
+// |--+ Profiler [S]
+//    |-- Total elapsed time                     [S0]  3.091 milliseconds.
+// |--+ Profiler [P]
+//    |-- elapsed time                           [P0] 87.550 milliseconds.
+//    |-- Total elapsed time                      [P] 87.559 milliseconds.
+// |-- Total elapsed time                  [TOP] 467.548 milliseconds.
+            
+public class Profiler {
+
+  final static int MIN_SW_NAME_LENGTH = 24;
+  final static int MIN_SW_ELAPSED_TIME_NUMBER_LENGTH = 9;
+
+  final String name;
+  final StopWatch globalStopWatch;
+
+  List<StopWatch> stopwatchList = new ArrayList<StopWatch>();
+  List<Object> childList = new ArrayList<Object>();
+
+  ProfilerRegistry profilerRegistry;
+  
+  public Profiler(String name) {
+    this.name = name;
+    this.globalStopWatch = new StopWatch(name);
+  }
+  
+  public String getName() {
+    return name;
+  }
+
+  public ProfilerRegistry getProfilerRegistry() {
+    return profilerRegistry;
+  }
+
+  public void setProfilerRegistry(ProfilerRegistry profilerRegistry) {
+    if(profilerRegistry == null) {
+      return;
+    }
+    this.profilerRegistry = profilerRegistry;
+    profilerRegistry.put(this);
+  }
+
+  public void start(String name) {
+    stopLastStopWatch();
+    StopWatch childSW = new StopWatch(name);
+    stopwatchList.add(childSW);
+    childList.add(childSW);
+  }
+
+  public Profiler startNested(String name) {
+    Profiler nestedProfiler = new Profiler(name);
+    nestedProfiler.setProfilerRegistry(profilerRegistry);
+    childList.add(nestedProfiler);
+    return nestedProfiler;
+  }
+
+  StopWatch getLastStopWatch() {
+    if (stopwatchList.size() > 0) {
+      return stopwatchList.get(stopwatchList.size() - 1);
+    } else {
+      return null;
+    }
+  }
+
+  void stopLastStopWatch() {
+    StopWatch last = getLastStopWatch();
+    if (last != null) {
+      last.stop();
+    }
+  }
+
+  void stopNestedProfilers() {
+    for (Object child : childList) {
+      if (child instanceof Profiler)
+        ((Profiler) child).stop();
+    }
+  }
+
+  public Profiler stop() {
+    stopLastStopWatch();
+    stopNestedProfilers();
+    globalStopWatch.stop();
+    return this;
+  }
+
+  public void print() {
+    DurationUnit du = Util.selectDurationUnitForDisplay(globalStopWatch);
+    String r = buildString(du, "+", "");
+    System.out.println(r);
+  }
+
+  private String buildString(DurationUnit du, String prefix, String indentation) {
+    StringBuffer buf = new StringBuffer();
+
+    
+    buf.append(prefix);
+    buf.append(" Profiler [");
+    buf.append(name);
+    buf.append("]");
+    buf.append(SpacePadder.LINE_SEP);
+    for (Object child : childList) {
+      if(child instanceof StopWatch) {
+       buildStringForChildStopWatch(buf, indentation, (StopWatch) child, du);
+      } else if(child instanceof Profiler) {
+        Profiler profiler = (Profiler) child;
+        profiler.stop();
+        String subString = profiler.buildString(du, "|--+", indentation + "   ");
+        buf.append(subString);
+      }
+    }
+    buildStringForGlobalStopWatch(buf, indentation, globalStopWatch, du);
+    return buf.toString();
+  }
+
+  private static void buildStringForChildStopWatch(StringBuffer buf,
+      String indentation, StopWatch sw, DurationUnit du) {
+
+    buf.append(indentation);
+    buf.append("|--");
+    buf.append(" elapsed time       ");
+    SpacePadder.leftPad(buf, "[" + sw.getName() + "]", MIN_SW_NAME_LENGTH);
+    buf.append(" ");
+    String timeStr = Util.durationInDunrationUnitsAsStr(sw.getResultInNanos(),
+        du);
+    SpacePadder.leftPad(buf, timeStr, MIN_SW_ELAPSED_TIME_NUMBER_LENGTH);
+    buf.append(" ");
+    Util.appendDurationUnitAsStr(buf, du);
+    buf.append(SpacePadder.LINE_SEP);
+  }
+
+  private static void buildStringForGlobalStopWatch(StringBuffer buf,
+      String indentation, StopWatch sw, DurationUnit du) {
+    buf.append(indentation);
+    buf.append("|--");
+    buf.append(" Total elapsed time ");
+    SpacePadder.leftPad(buf, "[" + sw.getName() + "]", MIN_SW_NAME_LENGTH);
+    buf.append(" ");
+    String timeStr = Util.durationInDunrationUnitsAsStr(sw.getResultInNanos(),
+        du);
+    SpacePadder.leftPad(buf, timeStr, MIN_SW_ELAPSED_TIME_NUMBER_LENGTH);
+    buf.append(" ");
+    Util.appendDurationUnitAsStr(buf, du);
+    buf.append(SpacePadder.LINE_SEP);
+  }
+
+}

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/ProfilerRegistry.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/ProfilerRegistry.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * A miniminalistic registry of profilers.
+ * 
+ * @author Ceki
+ */
+public class ProfilerRegistry {
+
+  private static final InheritableThreadLocal<ProfilerRegistry> inheritableThreadLocal = new InheritableThreadLocal<ProfilerRegistry>();
+
+  
+  Map<String, Profiler> profilerMap = new HashMap<String, Profiler>();
+
+  public void put(Profiler profiler) {
+    put(profiler.getName(), profiler);
+  }
+  
+  public void put(String name, Profiler profiler) {
+    profilerMap.put(name, profiler);
+  }
+  
+  
+  public static ProfilerRegistry getThreadContextInstance() {
+    ProfilerRegistry pr = inheritableThreadLocal.get();
+    if(pr == null) {
+      pr = new ProfilerRegistry();
+      inheritableThreadLocal.set(pr);
+    }
+    return pr;
+  }
+  
+  public Profiler get(String name) {
+    return profilerMap.get(name);
+  }
+  
+  public void clear() {
+    profilerMap.clear();
+  }
+}

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/SpacePadder.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/SpacePadder.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+public class SpacePadder {
+  public static final String LINE_SEP = System.getProperty("line.separator");
+  
+  final static String[] SPACES = { " ", "  ", "    ", "        ", // 1,2,4,8
+      // spaces
+      "                ", // 16 spaces
+      "                                " }; // 32 spaces
+
+  final static public void leftPad(StringBuffer buf, String s, int desiredLength) {
+    int actualLen = 0;
+    if (s != null) {
+      actualLen = s.length();
+    }
+    if (actualLen < desiredLength) {
+      spacePad(buf, desiredLength - actualLen);
+    }
+    if (s != null) {
+      buf.append(s);
+    }
+  }
+
+  final static public void rightPad(StringBuffer buf, String s, int desiredLength) {
+    int actualLen = 0;
+    if (s != null) {
+      actualLen = s.length();
+    }
+    if (s != null) {
+      buf.append(s);
+    }
+    if (actualLen < desiredLength) {
+      spacePad(buf, desiredLength - actualLen);
+    }
+  }
+  
+  /**
+   * Fast space padding method.
+   */
+  final static public void spacePad(StringBuffer sbuf, int length) {
+    while (length >= 32) {
+      sbuf.append(SPACES[5]);
+      length -= 32;
+    }
+
+    for (int i = 4; i >= 0; i--) {
+      if ((length & (1 << i)) != 0) {
+        sbuf.append(SPACES[i]);
+      }
+    }
+  }
+}

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/StopWatch.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/StopWatch.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+
+public class StopWatch {
+
+
+  enum Status {
+    STARTED, STOPPED;
+  }
+  
+  final String name;
+  final long startTime;
+  long stopTime;
+  Status status;
+
+  public StopWatch(String name) {
+    this.name = name;
+    this.startTime = System.nanoTime();
+    this.status = Status.STARTED;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public StopWatch stop() {
+    if(status == Status.STOPPED) {
+      return this;
+    } 
+    return stop(System.nanoTime());
+  }
+
+  public StopWatch stop(long stopTime) {
+    this.status = Status.STOPPED;
+    this.stopTime = stopTime;
+    return this;
+  }
+  
+  @Override
+  public String toString() {
+    StringBuffer buf = new StringBuffer();
+    buf.append("StopWatch [");
+    buf.append(name);
+    buf.append("] ");
+
+    switch (status) {
+    case STARTED:
+      buf.append("STARTED");
+      break;
+    case STOPPED:
+      buf.append("elapsed time: ");
+      buf.append(Util.durationInDunrationUnitsAsStr(getResultInNanos(), DurationUnit.MICROSECOND));
+      break;
+    default:
+      new IllegalStateException("Status " + status + " is not expected");
+    }
+    return buf.toString();
+  }
+
+  public final long getResultInNanos() {
+    if (status == Status.STARTED) {
+      return 0;
+    } else {
+      return stopTime - startTime;
+    }
+  }
+
+}

Added: slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Util.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/main/java/org/slf4j/profiler/Util.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+import java.text.DecimalFormat;
+
+class Util {
+
+  static final long NANOS_IN_ONE_MICROSECOND = 1000;
+  static final long NANOS_IN_ONE_MILLISECOND = NANOS_IN_ONE_MICROSECOND * 1000;
+  static final long NANOS_IN_ONE_SECOND =NANOS_IN_ONE_MILLISECOND * 1000;
+  private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.000");
+  
+  static DurationUnit selectDurationUnitForDisplay(StopWatch sw) {
+    return selectDurationUnitForDisplay(sw.getResultInNanos());
+  }
+  
+  static DurationUnit selectDurationUnitForDisplay(long durationInNanos) {
+    if (durationInNanos < 10*NANOS_IN_ONE_MICROSECOND) {
+      return DurationUnit.NANOSECOND;
+    } else if (durationInNanos < 10*NANOS_IN_ONE_MILLISECOND) {
+      return DurationUnit.MICROSECOND;
+    } else if (durationInNanos < 10*NANOS_IN_ONE_SECOND) {
+      return DurationUnit.MILLISSECOND;
+    } else {
+      return DurationUnit.SECOND;
+    }
+  }
+  
+  static public double convertToMicros(long nanos) {
+    return (double) nanos / NANOS_IN_ONE_MICROSECOND;
+  }
+
+  static public double convertToMillis(long nanos) {
+    return (double) nanos / NANOS_IN_ONE_MILLISECOND;
+  }
+
+  static public double convertToSeconds(long nanos) {
+    return ((double) nanos / NANOS_IN_ONE_SECOND);
+  }
+  
+  static String durationInDunrationUnitsAsStr(StringBuffer buf, StopWatch sw) {
+    DurationUnit du = selectDurationUnitForDisplay(sw);
+    return durationInDunrationUnitsAsStr(sw.getResultInNanos(), du);
+  }
+  
+  static String durationInDunrationUnitsAsStr(long nanos, DurationUnit durationUnit) {
+    StringBuffer buf = new StringBuffer();
+    switch (durationUnit) {
+    case NANOSECOND:
+      buf.append(nanos);
+      break;
+    case MICROSECOND:
+      double micros = convertToMicros(nanos);
+      buf.append(DECIMAL_FORMAT.format(micros));
+      break;
+    case MILLISSECOND:
+      double millis = convertToMillis(nanos);
+      buf.append(DECIMAL_FORMAT.format(millis));
+      break;
+    case SECOND:
+      double seconds = convertToSeconds(nanos);
+      buf.append(DECIMAL_FORMAT.format(seconds));
+      break;
+    }
+    return buf.toString();
+  }
+  
+  static void appendDurationUnitAsStr(StringBuffer buf, DurationUnit durationUnit) {
+    switch (durationUnit) {
+    case NANOSECOND:
+      buf.append("nanoseconds.");
+      break;
+    case MICROSECOND:
+      buf.append("microseconds.");
+      break;
+    case MILLISSECOND:
+      buf.append("milliseconds.");
+      break;
+    case SECOND:
+      buf.append(" seconds.");
+      break;
+    }
+  }
+}

Added: slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/PackageTest.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/PackageTest.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+
+import junit.framework.*;
+
+public class PackageTest extends TestCase {
+
+  public static Test suite() {
+    TestSuite suite = new TestSuite();
+    suite.addTestSuite(StopWatchTest.class);
+    suite.addTestSuite(ProfilerTest.class);
+    return suite;
+  }
+}
\ No newline at end of file

Added: slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/ProfilerTest.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/ProfilerTest.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+import junit.framework.TestCase;
+
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory; 
+
+public class ProfilerTest  extends TestCase{
+
+  Logger logger = LoggerFactory.getLogger(ProfilerTest.class);
+
+  public void smoke() {
+    Profiler profiler = new Profiler("SMOKE");
+    System.out.println("Hello");
+    profiler.stop();
+  }
+
+  public void testBasicProfiling() {
+    Profiler profiler = new Profiler("BAS");
+
+    profiler.start("doX");
+    doX(1);
+
+    profiler.start("doYYYYY");
+    for (int i = 0; i < 5; i++) {
+      doY(i);
+    }
+    profiler.start("doZ");
+    doZ(2);
+    profiler.stop().print();
+  }
+
+  public void X() {
+    Profiler profiler = new Profiler("BASIC");
+  
+
+  profiler.start("Subtask_1");
+  doX(1);
+     
+  profiler.start("Subtask_1");
+  for (int i = 0; i < 5; i++) {
+    doX(i);
+  }
+  profiler.start("doOther");
+  doX(2);
+  profiler.stop().print();
+  }
+
+
+  public void testNestedProfiling() {
+    Profiler profiler = new Profiler("BAS");
+
+    profiler.start("doX");
+    doX(1);
+
+    profiler.start("doYYYYY");
+    for (int i = 0; i < 5; i++) {
+      doY(i);
+    }
+    Profiler nested = profiler.startNested("subtask");
+    doSubtask(nested);
+    profiler.start("doZ");
+    doZ(2);
+    profiler.stop().print();
+  }
+
+  void doX(int millis) {
+    delay(millis);
+  }
+
+  public void doSubtask(Profiler nested) {
+    nested.start("n1");
+    doX(1);
+
+    nested.start("n2");
+    doX(5);
+    nested.stop();
+  }
+
+  void doY(int millis) {
+    delay(millis);
+  }
+
+  void doZ(int millis) {
+    delay(millis);
+  }
+
+  void delay(int millis) {
+    try {
+      Thread.sleep(millis);
+    } catch (InterruptedException e) {
+    }
+  }
+}

Added: slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/StopWatchTest.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/slf4j-ext/src/test/java/org/slf4j/profiler/StopWatchTest.java	Mon Jul 21 16:28:29 2008
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2004-2008 QOS.ch
+ * All rights reserved.
+ * 
+ * Permission is hereby granted, free  of charge, to any person obtaining
+ * a  copy  of this  software  and  associated  documentation files  (the
+ * "Software"), to  deal in  the Software without  restriction, including
+ * without limitation  the rights to  use, copy, modify,  merge, publish,
+ * distribute,  sublicense, and/or sell  copies of  the Software,  and to
+ * permit persons to whom the Software  is furnished to do so, subject to
+ * the following conditions:
+ * 
+ * The  above  copyright  notice  and  this permission  notice  shall  be
+ * included in all copies or substantial portions of the Software.
+ * 
+ * THE  SOFTWARE IS  PROVIDED  "AS  IS", WITHOUT  WARRANTY  OF ANY  KIND,
+ * EXPRESS OR  IMPLIED, INCLUDING  BUT NOT LIMITED  TO THE  WARRANTIES OF
+ * MERCHANTABILITY,    FITNESS    FOR    A   PARTICULAR    PURPOSE    AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+ * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+ * OF CONTRACT, TORT OR OTHERWISE,  ARISING FROM, OUT OF OR IN CONNECTION
+ * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+package org.slf4j.profiler;
+
+import junit.framework.TestCase;
+
+public class StopWatchTest extends TestCase {
+
+  public StopWatchTest(String name) {
+    super(name);
+  }
+
+  protected void setUp() throws Exception {
+    super.setUp();
+  }
+
+  protected void tearDown() throws Exception {
+    super.tearDown();
+  }
+  
+  public void testSelectDurationUnitForDisplay() throws InterruptedException {
+    assertEquals(DurationUnit.NANOSECOND, Util.selectDurationUnitForDisplay(10));
+    assertEquals(DurationUnit.NANOSECOND, Util.selectDurationUnitForDisplay(9*Util.NANOS_IN_ONE_MICROSECOND));
+    assertEquals(DurationUnit.MICROSECOND, Util.selectDurationUnitForDisplay(11*Util.NANOS_IN_ONE_MICROSECOND));
+    assertEquals(DurationUnit.MICROSECOND, Util.selectDurationUnitForDisplay(9*Util.NANOS_IN_ONE_MILLISECOND));
+    assertEquals(DurationUnit.MILLISSECOND, Util.selectDurationUnitForDisplay(11*Util.NANOS_IN_ONE_MILLISECOND));
+    assertEquals(DurationUnit.SECOND, Util.selectDurationUnitForDisplay(11*Util.NANOS_IN_ONE_SECOND));
+  }
+  
+}



More information about the slf4j-dev mailing list