1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.pool2.performance;
18
19 import java.time.Duration;
20 import java.util.ArrayList;
21 import java.util.List;
22 import java.util.concurrent.Callable;
23 import java.util.concurrent.ExecutionException;
24 import java.util.concurrent.ExecutorService;
25 import java.util.concurrent.Executors;
26 import java.util.concurrent.Future;
27
28 import org.apache.commons.pool2.impl.GenericObjectPool;
29
30
31
32
33 class PerformanceTest {
34 final class PerfTask implements Callable<TaskStats> {
35 final TaskStats taskStats = new TaskStats();
36 long borrowTimeNanos;
37 long returnTimeNanos;
38
39 @Override
40 public TaskStats call() {
41 runOnce();
42 for (int i = 0; i < nrIterations; i++) {
43 runOnce();
44 taskStats.totalBorrowNanos += borrowTimeNanos;
45 taskStats.totalReturnNanos += returnTimeNanos;
46 taskStats.nrSamples++;
47 if (logLevel >= 2) {
48 final String name = "thread" + Thread.currentThread().getName();
49 System.out.println(
50 "result " + taskStats.nrSamples + '\t' + name + '\t' + "borrow time: " + Duration.ofNanos(borrowTimeNanos) + '\t' + "return time: "
51 + Duration.ofNanos(returnTimeNanos) + '\t' + "waiting: " + taskStats.waiting + '\t' + "complete: " + taskStats.complete);
52 }
53 }
54 return taskStats;
55 }
56
57 public void runOnce() {
58 try {
59 taskStats.waiting++;
60 if (logLevel >= 5) {
61 final String name = "thread" + Thread.currentThread().getName();
62 System.out.println(name + " waiting: " + taskStats.waiting + " complete: " + taskStats.complete);
63 }
64 final long bbeginNanos = System.nanoTime();
65 final Integer o = pool.borrowObject();
66 final long bendNanos = System.nanoTime();
67 taskStats.waiting--;
68 if (logLevel >= 3) {
69 final String name = "thread" + Thread.currentThread().getName();
70 System.out.println(name + " waiting: " + taskStats.waiting + " complete: " + taskStats.complete);
71 }
72 final long rbeginNanos = System.nanoTime();
73 pool.returnObject(o);
74 final long rendNanos = System.nanoTime();
75 Thread.yield();
76 taskStats.complete++;
77 borrowTimeNanos = bendNanos - bbeginNanos;
78 returnTimeNanos = rendNanos - rbeginNanos;
79 } catch (final Exception e) {
80 e.printStackTrace();
81 }
82 }
83 }
84
85 private static final class TaskStats {
86 int waiting;
87 int complete;
88 long totalBorrowNanos;
89 long totalReturnNanos;
90 int nrSamples;
91 }
92
93 public static void main(final String[] args) {
94 final PerformanceTest test = new PerformanceTest();
95 test.setLogLevel(0);
96 System.out.println("Increase threads");
97 test.run(1, 50, 5, 5);
98 test.run(1, 100, 5, 5);
99 test.run(1, 200, 5, 5);
100 test.run(1, 400, 5, 5);
101 System.out.println("Increase threads & poolSize");
102 test.run(1, 50, 5, 5);
103 test.run(1, 100, 10, 10);
104 test.run(1, 200, 20, 20);
105 test.run(1, 400, 40, 40);
106 System.out.println("Increase maxIdle");
107 test.run(1, 400, 40, 5);
108 test.run(1, 400, 40, 40);
109
110
111
112 }
113
114 private int logLevel;
115 private int nrIterations = 5;
116 private GenericObjectPool<Integer> pool;
117
118 private void run(final int iterations, final int nrThreads, final int maxTotal, final int maxIdle) {
119 this.nrIterations = iterations;
120 final SleepingObjectFactory factory = new SleepingObjectFactory();
121 if (logLevel >= 4) {
122 factory.setDebug(true);
123 }
124 pool = new GenericObjectPool<>(factory);
125 pool.setMaxTotal(maxTotal);
126 pool.setMaxIdle(maxIdle);
127 pool.setTestOnBorrow(true);
128 final ExecutorService threadPool = Executors.newFixedThreadPool(nrThreads);
129 final List<Callable<TaskStats>> tasks = new ArrayList<>();
130 for (int i = 0; i < nrThreads; i++) {
131 tasks.add(new PerfTask());
132 Thread.yield();
133 }
134 if (logLevel >= 1) {
135 System.out.println("created");
136 }
137 Thread.yield();
138 List<Future<TaskStats>> futures = null;
139 try {
140 futures = threadPool.invokeAll(tasks);
141 } catch (final InterruptedException e) {
142 e.printStackTrace();
143 }
144 if (logLevel >= 1) {
145 System.out.println("started");
146 }
147 Thread.yield();
148 if (logLevel >= 1) {
149 System.out.println("go");
150 }
151 Thread.yield();
152 if (logLevel >= 1) {
153 System.out.println("finish");
154 }
155 final TaskStats aggregate = new TaskStats();
156 if (futures != null) {
157 for (final Future<TaskStats> future : futures) {
158 TaskStats taskStats = null;
159 try {
160 taskStats = future.get();
161 } catch (final InterruptedException | ExecutionException e) {
162 e.printStackTrace();
163 }
164 if (taskStats != null) {
165 aggregate.complete += taskStats.complete;
166 aggregate.nrSamples += taskStats.nrSamples;
167 aggregate.totalBorrowNanos += taskStats.totalBorrowNanos;
168 aggregate.totalReturnNanos += taskStats.totalReturnNanos;
169 aggregate.waiting += taskStats.waiting;
170 }
171 }
172 }
173 final Duration totalBorrowDuration = Duration.ofNanos(aggregate.totalBorrowNanos);
174 final Duration totalReturnDuration = Duration.ofNanos(aggregate.totalReturnNanos);
175 System.out.println("-----------------------------------------");
176 System.out.println("nrIterations: " + iterations);
177 System.out.println("nrThreads: " + nrThreads);
178 System.out.println("maxTotal: " + maxTotal);
179 System.out.println("maxIdle: " + maxIdle);
180 System.out.println("nrSamples: " + aggregate.nrSamples);
181 System.out.println("totalBorrowTime: " + totalBorrowDuration);
182 System.out.println("totalReturnTime: " + totalReturnDuration);
183 System.out.println("avg BorrowTime: " + totalBorrowDuration.dividedBy(aggregate.nrSamples));
184 System.out.println("avg ReturnTime: " + totalReturnDuration.dividedBy(aggregate.nrSamples));
185 threadPool.shutdown();
186 }
187
188 public void setLogLevel(final int i) {
189 logLevel = i;
190 }
191 }