Skip to content

Commit 49da64b

Browse files
committed
Increase default thread count - no reason not to
1 parent 097295f commit 49da64b

2 files changed

Lines changed: 136 additions & 3 deletions

File tree

src/main/java/com/applitools/imagetester/ImageTester.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727

2828
public class ImageTester {
2929
private static final String cur_ver = "3.9.1";
30+
private static final String DEFAULT_THREADS = String.valueOf(Runtime.getRuntime().availableProcessors() * 2);
3031

3132
public static void main(String[] args) {
3233
run(args);
@@ -145,7 +146,7 @@ public static void run(String[] args) {
145146

146147
File root = new File(cmd.getOptionValue("f", "."));
147148

148-
int maxThreads = Integer.parseInt(cmd.getOptionValue("th", "3"));
149+
int maxThreads = Integer.parseInt(cmd.getOptionValue("th", DEFAULT_THREADS));
149150
TestExecutor executor = new TestExecutor(maxThreads, factory, config);
150151

151152
Suite suite = Suite.create(root.getCanonicalFile(), config, executor);
@@ -266,7 +267,7 @@ private static void runTestWithBatchMapper(final Logger logger, final CommandLin
266267

267268
try {
268269
File root = new File(currentBatch.filePath);
269-
int maxThreads = Integer.parseInt(cmd.getOptionValue("th", "3"));
270+
int maxThreads = Integer.parseInt(cmd.getOptionValue("th", DEFAULT_THREADS));
270271
Suite suite = Suite.create(
271272
root.getCanonicalFile(),
272273
currentConfiguration,
@@ -455,7 +456,7 @@ private static Options getOptions() {
455456
.build());
456457
options.addOption(Option.builder("th")
457458
.longOpt("threads")
458-
.desc("Specify how many threads will be running the suite")
459+
.desc("Specify how many threads will be running the suite, default: 2 x available CPU cores")
459460
.hasArg()
460461
.argName("units")
461462
.build());
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
package Tests;
2+
3+
import com.applitools.imagetester.ImageTester;
4+
import org.junit.Assume;
5+
import org.junit.Test;
6+
7+
import javax.imageio.ImageIO;
8+
import java.awt.Color;
9+
import java.awt.Font;
10+
import java.awt.GradientPaint;
11+
import java.awt.Graphics2D;
12+
import java.awt.image.BufferedImage;
13+
import java.io.File;
14+
import java.io.IOException;
15+
import java.nio.file.Files;
16+
import java.nio.file.Path;
17+
import java.util.Comparator;
18+
19+
/**
20+
* Split-mode throughput benchmark. Generates N synthetic PNGs, runs ImageTester
21+
* in split mode (each image = 1 test) with two thread counts, reports wall time.
22+
*
23+
* mvn -P eyes-tests test -Dtest=BenchmarkTest -Dbench=true \
24+
* [-Dbench.count=40] [-Dbench.threadsA=3] [-Dbench.threadsB=16] \
25+
* [-Dbench.warmup=1] [-Dbench.iters=2]
26+
*/
27+
public class BenchmarkTest {
28+
29+
private static final String APP = "ImageTesterBenchmark";
30+
private static final int IMG_W = 800;
31+
private static final int IMG_H = 600;
32+
33+
@Test
34+
public void threadingBenchmark() throws IOException {
35+
Assume.assumeTrue(
36+
"skipped unless -Dbench=true",
37+
"true".equalsIgnoreCase(System.getProperty("bench"))
38+
);
39+
40+
int count = intProp("bench.count", 40);
41+
int threadsA = intProp("bench.threadsA", 3);
42+
int threadsB = intProp("bench.threadsB", Runtime.getRuntime().availableProcessors() * 2);
43+
int warmup = intProp("bench.warmup", 1);
44+
int iters = intProp("bench.iters", 2);
45+
46+
System.out.printf(
47+
"BENCH config: count=%d threadsA=%d threadsB=%d warmup=%d iters=%d%n",
48+
count, threadsA, threadsB, warmup, iters
49+
);
50+
51+
Path dir = generateFixtures(count);
52+
System.out.printf("BENCH fixtures: %s%n", dir);
53+
try {
54+
for (int i = 0; i < warmup; i++) {
55+
System.out.printf("BENCH warmup %d/%d (th=%d)%n", i + 1, warmup, threadsA);
56+
runOnce(dir, threadsA);
57+
}
58+
long[] a = new long[iters];
59+
long[] b = new long[iters];
60+
for (int i = 0; i < iters; i++) {
61+
System.out.printf("BENCH iter %d/%d A(th=%d)%n", i + 1, iters, threadsA);
62+
a[i] = runOnce(dir, threadsA);
63+
System.out.printf("BENCH iter %d/%d B(th=%d)%n", i + 1, iters, threadsB);
64+
b[i] = runOnce(dir, threadsB);
65+
}
66+
System.out.println("BENCH results:");
67+
report("A (th=" + threadsA + ")", a);
68+
report("B (th=" + threadsB + ")", b);
69+
} finally {
70+
deleteTree(dir);
71+
}
72+
}
73+
74+
private long runOnce(Path dir, int threads) {
75+
long t0 = System.nanoTime();
76+
ImageTester.run(new String[]{
77+
"-f", dir.toString(),
78+
"-a", APP,
79+
"-st",
80+
"-th", String.valueOf(threads)
81+
});
82+
return System.nanoTime() - t0;
83+
}
84+
85+
private Path generateFixtures(int count) throws IOException {
86+
Path dir = Files.createTempDirectory("imagetester-bench-");
87+
for (int i = 0; i < count; i++) {
88+
BufferedImage img = new BufferedImage(IMG_W, IMG_H, BufferedImage.TYPE_INT_RGB);
89+
Graphics2D g = img.createGraphics();
90+
float hue = (i * 37f) % 360f / 360f;
91+
g.setPaint(new GradientPaint(
92+
0, 0, Color.getHSBColor(hue, 0.55f, 0.92f),
93+
IMG_W, IMG_H, Color.WHITE
94+
));
95+
g.fillRect(0, 0, IMG_W, IMG_H);
96+
g.setColor(Color.BLACK);
97+
g.setFont(new Font("SansSerif", Font.BOLD, 48));
98+
g.drawString("img-" + i, 50, IMG_H / 2);
99+
g.dispose();
100+
File out = new File(dir.toFile(), String.format("img-%04d.png", i));
101+
ImageIO.write(img, "png", out);
102+
}
103+
return dir;
104+
}
105+
106+
private static void deleteTree(Path root) throws IOException {
107+
if (!Files.exists(root)) return;
108+
Files.walk(root)
109+
.sorted(Comparator.reverseOrder())
110+
.map(Path::toFile)
111+
.forEach(File::delete);
112+
}
113+
114+
private static int intProp(String key, int fallback) {
115+
String v = System.getProperty(key);
116+
return (v == null || v.isEmpty()) ? fallback : Integer.parseInt(v);
117+
}
118+
119+
private static void report(String name, long[] ns) {
120+
long sum = 0, min = Long.MAX_VALUE, max = 0;
121+
for (long v : ns) {
122+
sum += v;
123+
min = Math.min(min, v);
124+
max = Math.max(max, v);
125+
}
126+
double meanMs = sum / (double) ns.length / 1_000_000.0;
127+
System.out.printf(
128+
"BENCH %s: mean=%.0fms min=%.0fms max=%.0fms iters=%d%n",
129+
name, meanMs, min / 1e6, max / 1e6, ns.length
130+
);
131+
}
132+
}

0 commit comments

Comments
 (0)