Download Jar. Libraryless. Click here for Pure Java version (6950L/41K).
1 | // from https://github.com/ideastorm/Benchmark |
2 | |
3 | /* My results on ThinkPad, JDK 17: |
4 | |
5 | 3 Buffers |
6 | Direct Buffer Average 324.43 |
7 | Buffered Image Average 137.89 |
8 | Reuse Buffered Average 183.25 |
9 | ARGB Image Average 133.57 |
10 | Reuse ARGB Image Average 173.53 |
11 | Volatile Image Average 43159.51 |
12 | Reuse Volatile Average 521.36 |
13 | 2 Buffers |
14 | Direct Buffer Average 326.72 |
15 | Buffered Image Average 124.76 |
16 | Reuse Buffered Average 170.78 |
17 | ARGB Image Average 123.15 |
18 | Reuse ARGB Image Average 157.24 |
19 | Volatile Image Average 34659.11 |
20 | Reuse Volatile Average 731.17 |
21 | 1 Buffers |
22 | Direct Buffer Average 396.43 |
23 | Buffered Image Average 155.31 |
24 | Reuse Buffered Average 208.33 |
25 | ARGB Image Average 162.80 |
26 | Reuse ARGB Image Average 191.03 |
27 | Volatile Image Average 39582.93 |
28 | Reuse Volatile Average 752.04 |
29 | |
30 | */ |
31 | |
32 | p { Benchmark.main(args); } |
33 | |
34 | sclass Benchmark implements Callable<Long> { |
35 | |
36 | private static final int INNER_LOOP_COUNT = 250; |
37 | private static final int OUTER_LOOP_COUNT = 5; |
38 | private static final int NORMALIZE_LOOP_COUNT = 3; |
39 | |
40 | // Window Objects |
41 | static javax.swing.JFrame frame; |
42 | static javax.swing.JPanel panel; |
43 | |
44 | private final Consumer<Consumer<Graphics2D>> painter; |
45 | |
46 | private Benchmark(Consumer<Consumer<Graphics2D>> painter) { |
47 | this.painter = painter; |
48 | } |
49 | |
50 | @Override |
51 | public Long call() { |
52 | Font font = panel.getFont().deriveFont(30f); |
53 | long start = System.nanoTime(); |
54 | for (int i = 0; i < INNER_LOOP_COUNT; i++) { |
55 | final String frameCount = "" + i; |
56 | painter.accept((Graphics2D g) -> { |
57 | g.setColor(Color.BLACK); |
58 | g.setFont(font); |
59 | g.drawString(frameCount, 30, 100); |
60 | }); |
61 | } |
62 | long end = System.nanoTime(); |
63 | return end - start; |
64 | } |
65 | |
66 | public static void main(String[] args) { |
67 | |
68 | // Create JFrame |
69 | frame = new javax.swing.JFrame("Benchmark"); |
70 | frame.setDefaultCloseOperation(javax.swing.JFrame.DISPOSE_ON_CLOSE); |
71 | // Create JPanel |
72 | panel = new javax.swing.JPanel(false); |
73 | panel.setPreferredSize(new java.awt.Dimension(1280, 720)); |
74 | frame.setContentPane(panel); |
75 | |
76 | ClassLoader classloader = ClassLoader.getSystemClassLoader(); |
77 | |
78 | // Load Test Image |
79 | try { |
80 | testimage = loadImage2(#1103053); |
81 | blackimage = loadImage2(#1103052); |
82 | |
83 | // Set Window Visible and get Panel Graphics |
84 | frame.pack(); |
85 | frame.setVisible(true); |
86 | panelGraphics = panel.getGraphics(); |
87 | |
88 | for (int normalizeIndex = 0; normalizeIndex < NORMALIZE_LOOP_COUNT; normalizeIndex++) { |
89 | |
90 | printVars(+normalizeIndex); |
91 | |
92 | // Start Tests and Display Results |
93 | for (int bufferCount = 3; bufferCount > 0; bufferCount--) { |
94 | printVars(+bufferCount); |
95 | frame.createBufferStrategy(bufferCount); |
96 | List<Long> directBufferTimes = new ArrayList<>(); |
97 | List<Long> bufferedImageTimes = new ArrayList<>(); |
98 | List<Long> volatileImageTimes = new ArrayList<>(); |
99 | List<Long> bufferedArgbTimes = new ArrayList<>(); |
100 | List<Long> reuseBufferedTimes = new ArrayList<>(); |
101 | List<Long> reuseVolatileTimes = new ArrayList<>(); |
102 | List<Long> reuseArgbBufrTimes = new ArrayList<>(); |
103 | for (int i = 0; i < OUTER_LOOP_COUNT; i++) { |
104 | printVars(+normalizeIndex, +bufferCount, +i); |
105 | frame.setTitle("Benchmark - Direct Buffer"); |
106 | directBufferTimes.add(new Benchmark(Benchmark::drawDoubleBuffer).call()); |
107 | frame.setTitle("Benchmark - Buffered Image"); |
108 | bufferedImageTimes.add(new Benchmark(Benchmark::drawBufferedImage).call()); |
109 | frame.setTitle("Benchmark - Reuse Buffered Image"); |
110 | reuseBufferedTimes.add(new Benchmark(Benchmark::reuseBufferedImage).call()); |
111 | frame.setTitle("Benchmark - ARGB Buffered Image"); |
112 | bufferedArgbTimes.add(new Benchmark(Benchmark::drawArgbBufferedImage).call()); |
113 | frame.setTitle("Benchmark - Reuse ARGB Buffered Image"); |
114 | reuseArgbBufrTimes.add(new Benchmark(Benchmark::reuseArgbBufferedImage).call()); |
115 | frame.setTitle("Benchmark - Volatile Image"); |
116 | volatileImageTimes.add(new Benchmark(Benchmark::drawVolatileImage).call()); |
117 | frame.setTitle("Benchmark - Reuse Volatile Image"); |
118 | reuseVolatileTimes.add(new Benchmark(Benchmark::reuseVolatileImage).call()); |
119 | } |
120 | /* |
121 | * Java benchmarks usually have to "warm up". By running it multiple times and ignoring the first runs, we |
122 | * allow the JVM to normalize its heap allocation, so garbage collection doesn't affect the results as much. |
123 | */ |
124 | if (normalizeIndex == NORMALIZE_LOOP_COUNT - 1) { |
125 | // bufferedImageTimes.forEach(t -> System.out.printf("Buffered Image %01.2f\n", calcFps(t))); |
126 | // volatileImageTimes.forEach(t -> System.out.printf("Volatile Image %01.2f\n", calcFps(t))); |
127 | // directBufferTimes.forEach(t -> System.out.printf("Direct Buffer %01.2f\n", calcFps(t))); |
128 | System.out.printf("%d Buffers\n", bufferCount); |
129 | System.out.printf(" Direct Buffer Average %01.2f\n", directBufferTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
130 | System.out.printf(" Buffered Image Average %01.2f\n", bufferedImageTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
131 | System.out.printf(" Reuse Buffered Average %01.2f\n", reuseBufferedTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
132 | System.out.printf(" ARGB Image Average %01.2f\n", bufferedArgbTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
133 | System.out.printf("Reuse ARGB Image Average %01.2f\n", reuseArgbBufrTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
134 | System.out.printf(" Volatile Image Average %01.2f\n", volatileImageTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
135 | System.out.printf(" Reuse Volatile Average %01.2f\n", reuseVolatileTimes.stream().mapToDouble(Benchmark::calcFps).average().getAsDouble()); |
136 | } |
137 | } |
138 | } |
139 | |
140 | frame.setVisible(false); |
141 | } catch (Throwable e) { |
142 | e.printStackTrace(); |
143 | } |
144 | System.exit(0); //force shutdown |
145 | } |
146 | |
147 | static double calcFps(Long nanoTime) { |
148 | return INNER_LOOP_COUNT * 1_000_000_000.0 / nanoTime; |
149 | } |
150 | |
151 | // Test Image |
152 | static java.awt.Image testimage; |
153 | static java.awt.Image blackimage; |
154 | private static BufferedImage staticBuffered; |
155 | private static BufferedImage staticArgbBuffered; |
156 | private static VolatileImage staticVolatile; |
157 | |
158 | // Draw Graphics |
159 | static Graphics panelGraphics; |
160 | |
161 | static void drawUsingImageBuffer(Consumer<Graphics2D> frameMarker, Image buffer) { |
162 | Graphics2D imageGraphics = (Graphics2D) buffer.getGraphics(); |
163 | imageGraphics.drawImage(testimage, 0, 0, 1280, 720, null); |
164 | frameMarker.accept(imageGraphics); |
165 | panelGraphics.drawImage(buffer, 0, 0, 1280, 720, null); |
166 | } |
167 | |
168 | static void drawBufferedImage(Consumer<Graphics2D> frameMarker) { |
169 | BufferedImage buffer = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB); |
170 | drawUsingImageBuffer(frameMarker, buffer); |
171 | } |
172 | |
173 | static void reuseBufferedImage(Consumer<Graphics2D> frameMarker) { |
174 | if (staticBuffered == null) { |
175 | staticBuffered = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_RGB); |
176 | } |
177 | drawUsingImageBuffer(frameMarker, staticBuffered); |
178 | } |
179 | |
180 | static void drawArgbBufferedImage(Consumer<Graphics2D> frameMarker) { |
181 | BufferedImage buffer = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_ARGB); |
182 | drawUsingImageBuffer(frameMarker, buffer); |
183 | } |
184 | |
185 | static void reuseArgbBufferedImage(Consumer<Graphics2D> frameMarker) { |
186 | if (staticArgbBuffered == null) { |
187 | staticArgbBuffered = new BufferedImage(1280, 720, BufferedImage.TYPE_INT_ARGB); |
188 | } |
189 | drawUsingImageBuffer(frameMarker, staticArgbBuffered); |
190 | } |
191 | |
192 | static void drawVolatileImage(Consumer<Graphics2D> frameMarker) { |
193 | VolatileImage volatileImage = panel.createVolatileImage(1280, 720); |
194 | drawUsingImageBuffer(frameMarker, volatileImage); |
195 | } |
196 | |
197 | static void reuseVolatileImage(Consumer<Graphics2D> frameMarker) { |
198 | if (staticVolatile == null || staticVolatile.contentsLost()) { |
199 | staticVolatile = panel.createVolatileImage(1280, 720); |
200 | } |
201 | drawUsingImageBuffer(frameMarker, staticVolatile); |
202 | } |
203 | |
204 | static void drawDoubleBuffer(Consumer<Graphics2D> frameMarker) { |
205 | Insets insets = frame.getInsets(); |
206 | Toolkit.getDefaultToolkit().sync(); |
207 | BufferStrategy strategy = frame.getBufferStrategy(); |
208 | if (strategy != null) { |
209 | do { |
210 | do { |
211 | Graphics2D graphics = (Graphics2D) strategy.getDrawGraphics(); |
212 | graphics.translate(insets.left, insets.top); |
213 | graphics.drawImage(testimage, 0, 0, 1280, 720, null); |
214 | frameMarker.accept(graphics); |
215 | graphics.dispose(); |
216 | } while (strategy.contentsRestored()); |
217 | strategy.show(); |
218 | } while (strategy.contentsLost()); |
219 | } else { |
220 | Graphics2D graphics = (Graphics2D) panelGraphics; |
221 | graphics.drawImage(testimage, insets.left, insets.top, 1280, 720, null); |
222 | frameMarker.accept(graphics); |
223 | } |
224 | |
225 | } |
226 | } |
download show line numbers debug dex old transpilations
Travelled to 3 computer(s): bhatertpkbcr, mowyntqkapby, mqqgnosmbjvj
No comments. add comment
Snippet ID: | #1033787 |
Snippet name: | BufferedImage / VolatileImage Benchmark |
Eternal ID of this version: | #1033787/4 |
Text MD5: | 4d543aa3009d91c46d39ee58464decdb |
Transpilation MD5: | f5605a7f9124f7e3f1e00127b58d6a2e |
Author: | stefan |
Category: | javax / gui |
Type: | JavaX source code (desktop) |
Public (visible to everyone): | Yes |
Archived (hidden from active list): | No |
Created/modified: | 2022-01-04 21:39:13 |
Source code size: | 10412 bytes / 226 lines |
Pitched / IR pitched: | No / No |
Views / Downloads: | 315 / 989 |
Version history: | 3 change(s) |
Referenced in: | [show references] |