Skip to content

Commit

Permalink
test-utils: timer resolution added for stress tests
Browse files Browse the repository at this point in the history
Signed-off-by: Ketoth Xupack <ketoth.xupack@gmail.com>
  • Loading branch information
KetothXupack committed Dec 27, 2013
1 parent b17e20b commit 73fbd03
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 32 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ public void illegalArguments() throws Exception {
}
{
final Capture<Class<? extends ChannelHandler>> type = new Capture<>();
final Entry<Channel, ChannelPipeline> pair =
mockChannel(type, new RpcClientHandler());
final Entry<Channel, ChannelPipeline> pair = mockChannel(type, new RpcClientHandler());
final Channel channel = pair.getKey();
final ChannelPipeline pipeline = pair.getValue();
final ClientBootstrap bootstrap = createMock(ClientBootstrap.class);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,12 @@ public class AbstractStat implements IStressStat {
private final ConcurrentHashMap<Class, AtomicInteger> errorStats = new ConcurrentHashMap<>();
private final AtomicReference<Result> result = new AtomicReference<>();
private final String name;
private final int threadsCount;
private final TimerResolution resolution;

protected AbstractStat(final String name, final int threadsCount) {
protected AbstractStat(final TimerResolution resolution,
final String name) {
this.resolution = resolution;
this.name = name;
this.threadsCount = threadsCount;
}

@Override
Expand All @@ -53,9 +54,9 @@ protected final <T> T invoke(final int threadId,
new CopyOnWriteArrayList<Map.Entry<Long, Long>>());

try {
final long start = System.currentTimeMillis();
final long start = resolution.currentTime();
final T result = invoke.invoke();
final long diff = System.currentTimeMillis() - start;
final long diff = resolution.currentTime() - start;
timesPerThread.get(threadId).add(new ImmutablePair<>(start, diff));
return result;
} catch (final Exception e) {
Expand All @@ -79,6 +80,8 @@ protected final void calculate() {
times.addAll(e);
}

final int threadsCount = timesPerThread.size();

for (final Map.Entry<Long, Long> time : times) {
final Long runtimeInMillis = time.getValue();
totalDeltaMillis += runtimeInMillis;
Expand All @@ -89,7 +92,7 @@ protected final void calculate() {
minTime = runtimeInMillis;
}

final long second = time.getKey() / 1000;
final long second = time.getKey() / (long) resolution.getFactor();
if (!requests.containsKey(second)) {
requests.put(second, 0L);
}
Expand All @@ -100,7 +103,7 @@ protected final void calculate() {
1. * totalDeltaMillis / times.size();

final double throughput =
1000. * threadsCount * times.size() / totalDeltaMillis;
resolution.getFactor() * threadsCount * times.size() / totalDeltaMillis;

result.set(new Result(
requests,
Expand All @@ -125,14 +128,20 @@ public final String toString() {

builder.append("Min request time: ")
.append(res.getMinTime())
.append(" ")
.append(resolution.getName())
.append('\n');

builder.append("Max request time: ")
.append(res.getMaxTime())
.append(" ")
.append(resolution.getName())
.append('\n');

builder.append("Mean request time: ")
.append(res.getMeanRequestTime())
.append(" ")
.append(resolution.getName())
.append('\n');

builder.append("Overall errors: ")
Expand Down Expand Up @@ -165,7 +174,7 @@ public final String toString() {

builder.append("Throughput: ")
.append(res.getThroughput())
.append(" responses/sec")
.append(" resp/sec")
.append('\n');

return builder.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicReference;

/**
* @author <a href="mailto:ketoth.xupack@gmail.com">ketoth xupack</a>
Expand All @@ -13,9 +13,8 @@ protected abstract void doAction(final int threadId,
final int operationNumber)
throws Exception;

private final AtomicInteger threads = new AtomicInteger();

final ConcurrentMap<String, MultiInvocationStat> map = new ConcurrentHashMap<>();
private final AtomicReference<StressScenario> scenario= new AtomicReference<>();
private final ConcurrentMap<String, MultiInvocationStat> map = new ConcurrentHashMap<>();


protected final <T> T invoke(final int threadId,
Expand All @@ -34,12 +33,15 @@ public interface Invoke {
void invoke() throws Exception;
}

protected final void setTcreadsCount(final int threadsCount) {
threads.set(threadsCount);
protected final void setScenario(final StressScenario scenario) {
this.scenario.set(scenario);
}

private MultiInvocationStat getStat(final String name) {
map.putIfAbsent(name, new MultiInvocationStat(name, threads.get()));
map.putIfAbsent(name, new MultiInvocationStat(
this.scenario.get().getResolution(),
name));

return map.get(name);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,9 @@
* @since 2013-12-27 16:18
*/
public class MultiInvocationStat extends AbstractStat {
protected MultiInvocationStat(final String name, final int threadsCount) {
super(name, threadsCount);
protected MultiInvocationStat(final TimerResolution resolution,
final String name) {
super(resolution, name);
}

protected void invoke(final int threadId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
public class SingleInvocationStat extends AbstractStat {
private final NamedAction action;

public SingleInvocationStat(final NamedAction action, final int threadsCount) {
super(action.getName(), threadsCount);
public SingleInvocationStat(final TimerResolution resolution,
final NamedAction action) {
super(resolution, action.getName());
this.action = action;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,29 @@
* @since 2013-12-26 21:39
*/
public class StressScenario {
private StressScenario() {
private StressScenario(final TimerResolution resolution) {
this.resolution = resolution;
}

public static StressResult measure(final int threadsNumber,
private final TimerResolution resolution;

protected TimerResolution getResolution() {
return resolution;
}

public static StressScenario of(TimerResolution resolution) {
return new StressScenario(resolution);
}

public StressResult measure(final int threadsNumber,
final int cycleCount,
final NamedAction... actions)
throws InterruptedException {

final Map<String, SingleInvocationStat> result = new HashMap<>();
for (final NamedAction action : actions) {
result.put(action.getName(), new SingleInvocationStat(action, threadsNumber));
result.put(action.getName(), new SingleInvocationStat(resolution,
action));
}

final List<Thread> threads = new ArrayList<>();
Expand All @@ -43,15 +55,15 @@ public void run() {
}, "stress-worker-" + k));
}

final long overallStart = System.currentTimeMillis();
final long overallStart = resolution.currentTime();
for (final Thread thread : threads) {
thread.start();
}

for (final Thread thread : threads) {
thread.join();
}
final long overallEnd = System.currentTimeMillis();
final long overallEnd = resolution.currentTime();

final double overallApprox = (overallEnd - overallStart) / 1000.0;

Expand All @@ -68,12 +80,12 @@ public void run() {
overallApprox);
}

public static StressResult measure(final int threadsNumber,
final int cycleCount,
final Action action)
public StressResult measure(final int threadsNumber,
final int cycleCount,
final Action action)
throws InterruptedException {

action.setTcreadsCount(threadsNumber);
action.setScenario(this);
final List<Thread> threads = new ArrayList<>();

for (int i = 0; i < threadsNumber; i++) {
Expand All @@ -92,14 +104,16 @@ public void run() {
}, "stress-worker-" + k));
}

final long overallStart = System.currentTimeMillis();


final long overallStart = resolution.currentTime();
for (final Thread thread : threads) {
thread.start();
}
for (final Thread thread : threads) {
thread.join();
}
final long overallEnd = System.currentTimeMillis();
final long overallEnd = resolution.currentTime();

final double overallApprox = (overallEnd - overallStart) / 1000.0;

Expand All @@ -109,6 +123,7 @@ public void run() {
fails += stats.getFails();
}

action.setScenario(null);
return new StressResult(action.getMap(),
threadsNumber * cycleCount,
fails,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package org.nohope.test.stress;

/**
* @author <a href="mailto:ketoth.xupack@gmail.com">Ketoth Xupack</a>
* @since 2013-12-27 23:51
*/
public enum TimerResolution {
NANOSECONDS(1000 * 1000 * 1000, "ns") {
@Override
public long currentTime() {
return System.nanoTime();
}
},
MILLISECONDS(1000, "ms") {
@Override
public long currentTime() {
return System.currentTimeMillis();
}
};

private final double factor;
private final String name;

TimerResolution(final double factor, final String name) {
this.factor = factor;
this.name = name;
}

public abstract long currentTime();

public String getName() {
return name;
}

public double getFactor() {
return factor;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package org.nohope.test.stress;

import org.junit.Ignore;
import org.junit.Test;

/**
* @author <a href="mailto:ketoth.xupack@gmail.com">Ketoth Xupack</a>
* @since 2013-12-28 00:10
*/
public class StressScenarioTest {

@Test
@Ignore("for manual tests only")
public void roughTest() throws InterruptedException {
final StressResult m1 =
StressScenario.of(TimerResolution.MILLISECONDS)
.measure(50, 1000, new NamedAction("test1") {
@Override
protected void doAction(final int threadId, final int operationNumber)
throws Exception {
Thread.sleep(10);
}
});
final StressResult m2 =
StressScenario.of(TimerResolution.NANOSECONDS)
.measure(50, 1000, new NamedAction("test2") {
@Override
protected void doAction(final int threadId, final int operationNumber)
throws Exception {
Thread.sleep(10);
}
});

System.err.println(m1);
System.err.println(m2);
}
}

0 comments on commit 73fbd03

Please sign in to comment.