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)); + } + +} _______________________________________________ dev mailing list [email protected] http://www.slf4j.org/mailman/listinfo/dev
