Tracked objects. Now to set about to figuring out what to track.

git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@3075 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Michael Bayne
2004-08-13 23:44:16 +00:00
parent 3485019952
commit 864adbdc20
3 changed files with 115 additions and 2 deletions
@@ -0,0 +1,36 @@
//
// $Id: TrackedStreamableObject.java,v 1.1 2004/08/13 23:44:16 mdb Exp $
package com.threerings.io;
import com.samskivert.util.StringUtil;
import com.threerings.util.TrackedObject;
/**
* A simple serializable object implements the {@link Streamable}
* interface and provides a default {@link #toString} implementation which
* outputs all public members.
*/
public class TrackedStreamableObject extends TrackedObject
implements Streamable
{
/**
* Generates a string representation of this instance.
*/
public String toString ()
{
StringBuffer buf = new StringBuffer("[");
toString(buf);
return buf.append("]").toString();
}
/**
* Handles the toString-ification of all public members. Derived
* classes can override and include non-public members if desired.
*/
protected void toString (StringBuffer buf)
{
StringUtil.fieldsToString(buf, this);
}
}
@@ -1,5 +1,5 @@
//
// $Id: DObject.java,v 1.76 2004/07/07 04:08:41 mdb Exp $
// $Id: DObject.java,v 1.77 2004/08/13 23:44:16 mdb Exp $
package com.threerings.presents.dobj;
@@ -14,6 +14,7 @@ import com.samskivert.util.ListUtil;
import com.samskivert.util.StringUtil;
import com.threerings.io.Streamable;
import com.threerings.util.TrackedObject;
import com.threerings.presents.Log;
@@ -101,7 +102,8 @@ import com.threerings.presents.Log;
*
* Fields of type {@link Streamable} can also be used.
*/
public class DObject implements Streamable
public class DObject extends TrackedObject
implements Streamable
{
public DObject ()
{
@@ -0,0 +1,75 @@
//
// $Id: TrackedObject.java,v 1.1 2004/08/13 23:44:16 mdb Exp $
package com.threerings.util;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import com.samskivert.util.Tuple;
/**
* Used to perform rudimentary memory profiling on large, running systems
* where it is impractical to operate a real profiler. Instances of {@link
* TrackedObject} record their existence when constructed and their
* destruction when finalized which, combined with periodic queries of the
* current total object count (by class) logged and graphed (gnuplot is
* your friend), can provide an indication of systems that are improperly
* retaining references.
*/
public class TrackedObject
{
/** Records that this object came into existence. */
public TrackedObject ()
{
Class clazz = getClass();
synchronized (_map) {
int[] count = (int[])_map.get(clazz);
if (count == null) {
_map.put(clazz, count = new int[1]);
}
count[0]++;
}
}
/** Records that this object was collected. */
protected void finalize ()
{
Class clazz = getClass();
synchronized (_map) {
int[] count = (int[])_map.get(clazz);
if (count != null) {
count[0]--;
} else {
Log.warning("Finalized TrackedObject missing counter! " +
"[class=" + clazz + "].");
}
}
}
/**
* Returns a {@link Tuple} containing an array of {@link Class}
* instances and an <code>int[]</code> array that represent the number
* of outstanding instance of all {@link TrackedObject}s in the VM.
*/
public static Tuple getSnapshot ()
{
Class[] classes = null;
int[] counts = null;
synchronized (_map) {
classes = new Class[_map.size()];
counts = new int[_map.size()];
Iterator iter = _map.entrySet().iterator();
for (int ii = 0; iter.hasNext(); ii++) {
Map.Entry entry = (Map.Entry)iter.next();
classes[ii] = (Class)entry.getKey();
counts[ii] = ((int[])entry.getValue())[0];
}
}
return new Tuple(classes, counts);
}
/** Tracks a mapping from {@link Class} object to active count. */
protected static HashMap _map = new HashMap();
}