/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source 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, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
* Free SoftwareFoundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Sam
*/
package com.caucho.tools.profiler;
import java.util.*;
import com.caucho.util.*;
/**
* Represents a unique point at which profiling is performed. Obtained from a
* {@link ProfilerManager}. Equality between two instances of ProfilerPoint is
* based on the name only.
*/
public class ProfilerPoint
implements Comparable<ProfilerPoint>
{
private static final Profiler NOOP_PROFILER;
private final ProfilerManager _profilerManager;
private final String _name;
private LruCache<String,ProfilerPoint> _children;
private long _time;
private long _invocationCount;
private long _minTime = Long.MAX_VALUE;
private long _maxTime = Long.MIN_VALUE;
ProfilerPoint(ProfilerManager profilerManager, String name)
{
assert profilerManager != null;
assert name != null;
_profilerManager = profilerManager;
_name = name;
}
protected ProfilerManager getProfilerManager()
{
return _profilerManager;
}
public String getName()
{
return _name;
}
public ProfilerPoint addProfilerPoint(String name)
{
synchronized (this) {
if (_children == null)
_children = new LruCache<String,ProfilerPoint>(1024);
ProfilerPoint child = _children.get(name);
if (child == null) {
child = create(name);
_children.put(name, child);
}
return child;
}
}
protected ProfilerPoint create(String name)
{
return new ProfilerPoint(getProfilerManager(), name);
}
public Profiler start()
{
if (!_profilerManager.isEnabled())
return NOOP_PROFILER;
ThreadProfiler profiler = ThreadProfiler.current();
profiler.start(this);
return profiler;
}
protected Profiler start(ProfilerPoint parent)
{
if (!getProfilerManager().isEnabled())
return NOOP_PROFILER;
ThreadProfiler profiler = ThreadProfiler.current();
profiler.start(parent, this);
return profiler;
}
/**
* Caller must synchronize on this ProfilerPoint while it uses the returned
* map.
*/
List<ProfilerPoint> getChildren()
{
if (_children == null)
return Collections.emptyList();
else {
ArrayList<ProfilerPoint> children = new ArrayList<ProfilerPoint>();
Iterator<ProfilerPoint> iter = _children.values();
while (iter.hasNext())
children.add(iter.next());
return children;
}
}
/**
* Increment the invocation count and add time.
*
* @param totalTime
*/
void update(long totalTime)
{
synchronized (this) {
_invocationCount++;
if (_invocationCount > 0) {
_time += totalTime;
}
if (totalTime < _minTime)
_minTime = totalTime;
if (_maxTime < totalTime)
_maxTime = totalTime;
}
}
/**
* Time for this node in nanoseconds, does not include the time for child
* nodes.
*/
public long getTime()
{
return _time;
}
/**
* Minimum time for this node in nanoseconds, does not include
* the time for child nodes.
*/
public long getMinTime()
{
return _minTime;
}
/**
* Minimum time for this node in nanoseconds, does not include
* the time for child nodes.
*/
public long getMaxTime()
{
return _maxTime;
}
void incrementInvocationCount()
{
synchronized (this) {
_invocationCount++;
}
}
public long getInvocationCount()
{
return _invocationCount;
}
/**
* Drop all of the children
*/
void reset()
{
_children = null;
_time = 0;
_invocationCount = 0;
_minTime = Long.MAX_VALUE;
_maxTime = Long.MIN_VALUE;
}
public boolean equals(Object o)
{
if (o == this)
return true;
if (!(o instanceof ProfilerPoint))
return false;
ProfilerPoint point = (ProfilerPoint) o;
return getName().equals(point.getName());
}
public int compareTo(ProfilerPoint point)
{
return getName().compareTo(point.getName());
}
public int hashCode()
{
return getName().hashCode();
}
public String toString()
{
return "ProfilerPoint[" + getName() + "]";
}
static {
NOOP_PROFILER = new Profiler() {
public void finish()
{
}
public String toString()
{
return "NoopProfiler[]";
}
};
}
}