1 /*
2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package sun.java2d.marlin;
27 
28 import java.security.AccessController;
29 import java.security.PrivilegedAction;
30 import java.util.Timer;
31 import java.util.TimerTask;
32 import java.util.concurrent.ConcurrentLinkedQueue;
33 import static sun.java2d.marlin.MarlinUtils.logInfo;
34 import sun.java2d.marlin.stats.Histogram;
35 import sun.java2d.marlin.stats.Monitor;
36 import sun.java2d.marlin.stats.StatLong;
37 import sun.misc.ThreadGroupUtils;
38 
39 /**
40  * This class gathers global rendering statistics for debugging purposes only
41  */
42 public final class RendererStats implements MarlinConst {
43 
44     // singleton
45     private static volatile RendererStats singleton = null;
46 
getInstance()47     static RendererStats getInstance() {
48         if (singleton == null) {
49             singleton = new RendererStats();
50         }
51         return singleton;
52     }
53 
dumpStats()54     public static void dumpStats() {
55         if (singleton != null) {
56             singleton.dump();
57         }
58     }
59 
60     /* RendererContext collection as hard references
61        (only used for debugging purposes) */
62     final ConcurrentLinkedQueue<RendererContext> allContexts
63         = new ConcurrentLinkedQueue<RendererContext>();
64     // stats
65     final StatLong stat_cache_rowAA
66         = new StatLong("cache.rowAA");
67     final StatLong stat_cache_rowAAChunk
68         = new StatLong("cache.rowAAChunk");
69     final StatLong stat_cache_tiles
70         = new StatLong("cache.tiles");
71     final StatLong stat_rdr_poly_stack_curves
72         = new StatLong("renderer.poly.stack.curves");
73     final StatLong stat_rdr_poly_stack_types
74         = new StatLong("renderer.poly.stack.types");
75     final StatLong stat_rdr_addLine
76         = new StatLong("renderer.addLine");
77     final StatLong stat_rdr_addLine_skip
78         = new StatLong("renderer.addLine.skip");
79     final StatLong stat_rdr_curveBreak
80         = new StatLong("renderer.curveBreakIntoLinesAndAdd");
81     final StatLong stat_rdr_curveBreak_dec
82         = new StatLong("renderer.curveBreakIntoLinesAndAdd.dec");
83     final StatLong stat_rdr_curveBreak_inc
84         = new StatLong("renderer.curveBreakIntoLinesAndAdd.inc");
85     final StatLong stat_rdr_quadBreak
86         = new StatLong("renderer.quadBreakIntoLinesAndAdd");
87     final StatLong stat_rdr_quadBreak_dec
88         = new StatLong("renderer.quadBreakIntoLinesAndAdd.dec");
89     final StatLong stat_rdr_edges
90         = new StatLong("renderer.edges");
91     final StatLong stat_rdr_edges_count
92         = new StatLong("renderer.edges.count");
93     final StatLong stat_rdr_edges_resizes
94         = new StatLong("renderer.edges.resize");
95     final StatLong stat_rdr_activeEdges
96         = new StatLong("renderer.activeEdges");
97     final StatLong stat_rdr_activeEdges_updates
98         = new StatLong("renderer.activeEdges.updates");
99     final StatLong stat_rdr_activeEdges_adds
100         = new StatLong("renderer.activeEdges.adds");
101     final StatLong stat_rdr_activeEdges_adds_high
102         = new StatLong("renderer.activeEdges.adds_high");
103     final StatLong stat_rdr_crossings_updates
104         = new StatLong("renderer.crossings.updates");
105     final StatLong stat_rdr_crossings_sorts
106         = new StatLong("renderer.crossings.sorts");
107     final StatLong stat_rdr_crossings_bsearch
108         = new StatLong("renderer.crossings.bsearch");
109     final StatLong stat_rdr_crossings_msorts
110         = new StatLong("renderer.crossings.msorts");
111     // growable arrays
112     final StatLong stat_array_dasher_dasher
113         = new StatLong("array.dasher.dasher.d_float");
114     final StatLong stat_array_dasher_firstSegmentsBuffer
115         = new StatLong("array.dasher.firstSegmentsBuffer.d_float");
116     final StatLong stat_array_stroker_polystack_curves
117         = new StatLong("array.stroker.polystack.curves.d_float");
118     final StatLong stat_array_stroker_polystack_curveTypes
119         = new StatLong("array.stroker.polystack.curveTypes.d_byte");
120     final StatLong stat_array_marlincache_rowAAChunk
121         = new StatLong("array.marlincache.rowAAChunk.d_byte");
122     final StatLong stat_array_marlincache_touchedTile
123         = new StatLong("array.marlincache.touchedTile.int");
124     final StatLong stat_array_renderer_alphaline
125         = new StatLong("array.renderer.alphaline.int");
126     final StatLong stat_array_renderer_crossings
127         = new StatLong("array.renderer.crossings.int");
128     final StatLong stat_array_renderer_aux_crossings
129         = new StatLong("array.renderer.aux_crossings.int");
130     final StatLong stat_array_renderer_edgeBuckets
131         = new StatLong("array.renderer.edgeBuckets.int");
132     final StatLong stat_array_renderer_edgeBucketCounts
133         = new StatLong("array.renderer.edgeBucketCounts.int");
134     final StatLong stat_array_renderer_edgePtrs
135         = new StatLong("array.renderer.edgePtrs.int");
136     final StatLong stat_array_renderer_aux_edgePtrs
137         = new StatLong("array.renderer.aux_edgePtrs.int");
138     // histograms
139     final Histogram hist_rdr_crossings
140         = new Histogram("renderer.crossings");
141     final Histogram hist_rdr_crossings_ratio
142         = new Histogram("renderer.crossings.ratio");
143     final Histogram hist_rdr_crossings_adds
144         = new Histogram("renderer.crossings.adds");
145     final Histogram hist_rdr_crossings_msorts
146         = new Histogram("renderer.crossings.msorts");
147     final Histogram hist_rdr_crossings_msorts_adds
148         = new Histogram("renderer.crossings.msorts.adds");
149     final Histogram hist_tile_generator_alpha
150         = new Histogram("tile_generator.alpha");
151     final Histogram hist_tile_generator_encoding
152         = new Histogram("tile_generator.encoding");
153     final Histogram hist_tile_generator_encoding_dist
154         = new Histogram("tile_generator.encoding.dist");
155     final Histogram hist_tile_generator_encoding_ratio
156         = new Histogram("tile_generator.encoding.ratio");
157     final Histogram hist_tile_generator_encoding_runLen
158         = new Histogram("tile_generator.encoding.runLen");
159     // all stats
160     final StatLong[] statistics = new StatLong[]{
161         stat_cache_rowAA,
162         stat_cache_rowAAChunk,
163         stat_cache_tiles,
164         stat_rdr_poly_stack_types,
165         stat_rdr_poly_stack_curves,
166         stat_rdr_addLine,
167         stat_rdr_addLine_skip,
168         stat_rdr_curveBreak,
169         stat_rdr_curveBreak_dec,
170         stat_rdr_curveBreak_inc,
171         stat_rdr_quadBreak,
172         stat_rdr_quadBreak_dec,
173         stat_rdr_edges,
174         stat_rdr_edges_count,
175         stat_rdr_edges_resizes,
176         stat_rdr_activeEdges,
177         stat_rdr_activeEdges_updates,
178         stat_rdr_activeEdges_adds,
179         stat_rdr_activeEdges_adds_high,
180         stat_rdr_crossings_updates,
181         stat_rdr_crossings_sorts,
182         stat_rdr_crossings_bsearch,
183         stat_rdr_crossings_msorts,
184         hist_rdr_crossings,
185         hist_rdr_crossings_ratio,
186         hist_rdr_crossings_adds,
187         hist_rdr_crossings_msorts,
188         hist_rdr_crossings_msorts_adds,
189         hist_tile_generator_alpha,
190         hist_tile_generator_encoding,
191         hist_tile_generator_encoding_dist,
192         hist_tile_generator_encoding_ratio,
193         hist_tile_generator_encoding_runLen,
194         stat_array_dasher_dasher,
195         stat_array_dasher_firstSegmentsBuffer,
196         stat_array_stroker_polystack_curves,
197         stat_array_stroker_polystack_curveTypes,
198         stat_array_marlincache_rowAAChunk,
199         stat_array_marlincache_touchedTile,
200         stat_array_renderer_alphaline,
201         stat_array_renderer_crossings,
202         stat_array_renderer_aux_crossings,
203         stat_array_renderer_edgeBuckets,
204         stat_array_renderer_edgeBucketCounts,
205         stat_array_renderer_edgePtrs,
206         stat_array_renderer_aux_edgePtrs
207     };
208     // monitors
209     final Monitor mon_pre_getAATileGenerator
210         = new Monitor("MarlinRenderingEngine.getAATileGenerator()");
211     final Monitor mon_npi_currentSegment
212         = new Monitor("NormalizingPathIterator.currentSegment()");
213     final Monitor mon_rdr_addLine
214         = new Monitor("Renderer.addLine()");
215     final Monitor mon_rdr_endRendering
216         = new Monitor("Renderer.endRendering()");
217     final Monitor mon_rdr_endRendering_Y
218         = new Monitor("Renderer._endRendering(Y)");
219     final Monitor mon_rdr_copyAARow
220         = new Monitor("Renderer.copyAARow()");
221     final Monitor mon_pipe_renderTiles
222         = new Monitor("AAShapePipe.renderTiles()");
223     final Monitor mon_ptg_getAlpha
224         = new Monitor("MarlinTileGenerator.getAlpha()");
225     final Monitor mon_debug
226         = new Monitor("DEBUG()");
227     // all monitors
228     final Monitor[] monitors = new Monitor[]{
229         mon_pre_getAATileGenerator,
230         mon_npi_currentSegment,
231         mon_rdr_addLine,
232         mon_rdr_endRendering,
233         mon_rdr_endRendering_Y,
234         mon_rdr_copyAARow,
235         mon_pipe_renderTiles,
236         mon_ptg_getAlpha,
237         mon_debug
238     };
239 
RendererStats()240     private RendererStats() {
241         super();
242 
243         AccessController.doPrivileged(
244             (PrivilegedAction<Void>) () -> {
245                 final Thread hook = new Thread(
246                     ThreadGroupUtils.getRootThreadGroup(),
247                     new Runnable() {
248                         @Override
249                         public void run() {
250                             dump();
251                         }
252                     },
253                     "MarlinStatsHook"
254                 );
255                 hook.setContextClassLoader(null);
256                 Runtime.getRuntime().addShutdownHook(hook);
257 
258                 if (useDumpThread) {
259                     final Timer statTimer = new Timer("RendererStats");
260                     statTimer.scheduleAtFixedRate(new TimerTask() {
261                         @Override
262                         public void run() {
263                             dump();
264                         }
265                     }, statDump, statDump);
266                 }
267                 return null;
268             }
269         );
270     }
271 
dump()272     void dump() {
273         if (doStats) {
274             ArrayCache.dumpStats();
275         }
276         final RendererContext[] all = allContexts.toArray(
277                                           new RendererContext[allContexts.size()]);
278         for (RendererContext rdrCtx : all) {
279             logInfo("RendererContext: " + rdrCtx.name);
280 
281             if (doMonitors) {
282                 for (Monitor monitor : monitors) {
283                     if (monitor.count != 0) {
284                         logInfo(monitor.toString());
285                     }
286                 }
287                 // As getAATileGenerator percents:
288                 final long total = mon_pre_getAATileGenerator.sum;
289                 if (total != 0L) {
290                     for (Monitor monitor : monitors) {
291                         logInfo(monitor.name + " : "
292                                 + ((100d * monitor.sum) / total) + " %");
293                     }
294                 }
295                 if (doFlushMonitors) {
296                     for (Monitor m : monitors) {
297                         m.reset();
298                     }
299                 }
300             }
301 
302             if (doStats) {
303                 for (StatLong stat : statistics) {
304                     if (stat.count != 0) {
305                         logInfo(stat.toString());
306                         stat.reset();
307                     }
308                 }
309                 // IntArrayCaches stats:
310                 final RendererContext.ArrayCachesHolder holder
311                     = rdrCtx.getArrayCachesHolder();
312 
313                 logInfo("Array caches for thread: " + rdrCtx.name);
314 
315                 for (IntArrayCache cache : holder.intArrayCaches) {
316                     cache.dumpStats();
317                 }
318 
319                 logInfo("Dirty Array caches for thread: " + rdrCtx.name);
320 
321                 for (IntArrayCache cache : holder.dirtyIntArrayCaches) {
322                     cache.dumpStats();
323                 }
324                 for (FloatArrayCache cache : holder.dirtyFloatArrayCaches) {
325                     cache.dumpStats();
326                 }
327                 for (ByteArrayCache cache : holder.dirtyByteArrayCaches) {
328                     cache.dumpStats();
329                 }
330             }
331         }
332     }
333 }
334