Skip to content
This repository has been archived by the owner on Feb 20, 2023. It is now read-only.

Commit

Permalink
Implement object pooling for CallStackElements
Browse files Browse the repository at this point in the history
  • Loading branch information
Felix Barnsteiner committed Jul 16, 2015
1 parent 24ec2d2 commit 15fe850
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
package org.stagemonitor.requestmonitor;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.UUID;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
Expand All @@ -11,11 +16,6 @@
import org.stagemonitor.core.util.StringUtils;
import org.stagemonitor.requestmonitor.profiler.CallStackElement;

import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Date;
import java.util.UUID;

/**
* A request trace is a data structure containing all the important information about a request.
*/
Expand Down Expand Up @@ -279,4 +279,9 @@ public interface GetNameCallback {
*/
String getName();
}

@Override
public void finalize() {
callStack.recycle();
}
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package org.stagemonitor.requestmonitor.profiler;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Queue;

import com.fasterxml.jackson.annotation.JsonIgnore;

Expand All @@ -25,26 +27,51 @@ public class CallStackElement {
private long executionTime;
private List<CallStackElement> children = new LinkedList<CallStackElement>();

public CallStackElement(String signature) {
this(null, signature);
private static ThreadLocal<Queue<CallStackElement>> objectPool = new ThreadLocal<Queue<CallStackElement>>() {
@Override
protected Queue<CallStackElement> initialValue() {
return new LimitedQueue<CallStackElement>(10000);
}
};

public static CallStackElement createParent(String signature) {
return CallStackElement.create(null, signature, System.nanoTime());
}

public CallStackElement(CallStackElement parent, String signature) {
this(parent, signature, System.nanoTime());
public static CallStackElement create(CallStackElement parent, String signature) {
return CallStackElement.create(parent, signature, System.nanoTime());
}

/**
* This static factory method also sets the parent-child relationships.
* @param parent the parent
* @param startTimestamp the timestamp at the beginning of the method
*/
public CallStackElement(CallStackElement parent, String signature, long startTimestamp) {
executionTime = startTimestamp;
this.signature = signature;
public static CallStackElement create(CallStackElement parent, String signature, long startTimestamp) {
final Queue<CallStackElement> pool = objectPool.get();
CallStackElement cse = pool.poll();
if (cse == null) {
cse = new CallStackElement();
}

cse.executionTime = startTimestamp;
cse.signature = signature;
if (parent != null) {
this.parent = parent;
parent.getChildren().add(this);
cse.parent = parent;
parent.getChildren().add(cse);
}
return cse;
}

public void recycle() {
parent = null;
signature = null;
executionTime = 0;
for (CallStackElement child : children) {
child.recycle();
}
children.clear();
objectPool.get().add(this);
}

public void removeCallsFasterThan(long thresholdNs) {
Expand Down Expand Up @@ -250,4 +277,19 @@ private boolean isLastChild() {
private boolean isRoot() {
return parent == null;
}

private static class LimitedQueue<T> extends ArrayDeque<T> {
private final int limit;

private LimitedQueue(int limit) {
super(limit);
this.limit = limit;
}

@Override
public boolean add(T t) {
return size() != limit && super.add(t);
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ private Profiler() {
public static void start(String signature) {
final CallStackElement parent = methodCallParent.get();
if (parent != null) {
methodCallParent.set(new CallStackElement(parent, signature));
methodCallParent.set(CallStackElement.create(parent, signature));
}
}

Expand All @@ -32,7 +32,7 @@ public static void addIOCall(String signature, long executionTimeNanos) {

public static void addCall(String signature, long executionTimeNanos) {
final CallStackElement currentCall = methodCallParent.get();
new CallStackElement(currentCall, signature, executionTimeNanos);
CallStackElement.create(currentCall, signature, executionTimeNanos);
}

public static boolean isProfilingActive() {
Expand All @@ -46,7 +46,7 @@ public static boolean isProfilingActive() {
* @return the root of the call stack
*/
public static CallStackElement activateProfiling(String signature) {
CallStackElement root = new CallStackElement(signature);
CallStackElement root = CallStackElement.createParent(signature);
methodCallParent.set(root);
return root;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ public void printPercentAsBar() throws Exception {

@Test
public void testGetShortSignature() {
CallStackElement callStackElement = new CallStackElement("public void org.stagemonitor.requestmonitor.profiler.CallStackElementTest.testGetShortSignature()");
CallStackElement callStackElement = CallStackElement.createParent("public void org.stagemonitor.requestmonitor.profiler.CallStackElementTest.testGetShortSignature()");
Assert.assertEquals("CallStackElementTest#testGetShortSignature", callStackElement.getShortSignature());
}

@Test
public void testGetShortSignatureTotal() {
CallStackElement callStackElement = new CallStackElement("total");
CallStackElement callStackElement = CallStackElement.createParent("total");
Assert.assertNull(callStackElement.getShortSignature());
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public void testProfiler() {
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from user \n" +
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from address \n" +
"000250.00 025% ||:------- 000250.00 025% ||:------- `-- method1_2_1()\n", callStackElement.toString());
callStackElement.recycle();
}

@Test
Expand All @@ -129,6 +130,7 @@ public void testRemoveCallsFasterThan() {
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from user \n" +
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from address \n" +
"000250.00 025% ||:------- 000250.00 025% ||:------- `-- method1_2_1()\n", callStackElement.toString());
callStackElement.recycle();
}

@Test
Expand All @@ -149,6 +151,7 @@ public void testRemoveCallsFasterThanNotIncluded() {
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from user \n" +
"000050.00 005% :--------- 000050.00 005% :--------- |-- select * from address \n" +
"000250.00 025% ||:------- 000250.00 025% ||:------- `-- method1_2_1()\n", callStackElement.toString());
callStackElement.recycle();
}

@Test
Expand Down

0 comments on commit 15fe850

Please sign in to comment.