• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2022 Google Inc.
3  *
4  * Use of this source code is governed by a BSD-style license that can be
5  * found in the LICENSE file.
6  *
7  * This is an experimental (and probably temporary) solution that allows
8  * to compare performance SkVM blitters vs RasterPipeline blitters.
9  * In addition to measuring performance (which is questionable) it also produces
10  * other counts (pixels, scanlines) and more detailed traces that
11  * can explain the current results (SkVM is slower) and help improve it.
12  * The entire code is hidden under build flag skia_compare_vm_vs_rp=true
13  * and will not appear at all without it.
14  */
15 
16 #ifndef SkBlitterTraceCommon_DEFINED
17 #define SkBlitterTraceCommon_DEFINED
18 
19 #include <inttypes.h>
20 #include <unordered_map>
21 
22 #define SK_BLITTER_TRACE_NO_CODE do {} while (0)
23 
24 #ifdef SKIA_COMPARE_VM_VS_RP
25 
26 #include "src/utils/SkCycles.h"
27 
28 class SkBlitterTrace {
29 /*
30  * This class collects information for RasterPipeLine vs SkVM
31  * performance comparison.
32  * How to get the comparison table:
33  * 1. Add to your Release/args.gn an argument: skia_compare_vm_vs_rp=true
34  *    Build nanobench.
35  * 2. Run nanobench for SkVM:
36  *    []/Release/nanobench
37  *    --csv --config 8888 --skvm --loops 100 --samples 1
38  *    --match $(ls skps | grep --invert-match svg ) 2>&1 | tee VM.data
39  * 3. Run nanobench for RasterPipeLine:
40  *    []/Release/nanobench
41  *    --csv --config 8888 --forceRasterPipeline --loops 100
42  *    --samples 1 --match $(ls skps | grep --invert-match svg )
43  *    2>&1 | tee RP.data
44  * 4. Extract the information side-by-side:
45  *    awk 'BEGIN {OFS=","; fileNum = 0} ($2 ~ /MB/) && fileNum == 0
46  *    {vmvmcycles[$3] = $6; vmvmscan[$3] = $8; vmvmpixels[$3] = $10;
47  *    vmvminterp[$3] = $11;  vmrpcycle[$3] = $14; vmrpscan[$3] = $16;
48  *    vmrppixels[$3] = $18} ($2 ~ /MB/) && fileNum == 1  {print $3,
49  *    vmvmcycles[$3], vmvmscan[$3], vmvmpixels[$3], vmvminterp[$3], $6, $8,
50  *    $10, $11, $14, $16, $18} ENDFILE {fileNum += 1}'
51  *    VM.data RP.data > compare.csv
52  * 5. Open the compare.csv table in Google Spreadsheets.
53  *     You will get columns [A:P]. Add 4 more columns with formulas:
54  *     Q: =B/M-1
55  *     R: =N-C
56  *     S: =O-D
57  *     T: =2*(S<>0)+(R<>0)
58  *     To be honest R, S, T columns are here for checking only (they all
59  *     supposed to have zero values in them)
60  *     Column Q shows the actual performance difference. Negative value means
61  *     that wins SkVM, positive - RasterPipeLine.
62  */
63 public:
64     SkBlitterTrace(const char* header, bool traceSteps = false)
fHeader(header)65         : fHeader(header), fTraceSteps(traceSteps) { }
66 
67     SkBlitterTrace& operator= (const SkBlitterTrace&) = default;
68 
addTrace(const char * name,uint64_t cycles,uint64_t scanLines,uint64_t pixels)69     void addTrace(const char* name, uint64_t cycles, uint64_t scanLines, uint64_t pixels) {
70         fCycles += cycles;
71         fScanlines += scanLines;
72         fPixels += pixels;
73         if (fTraceSteps) {
74             printIncrements(name, cycles, scanLines, pixels);
75         }
76     }
77 
reset()78     void reset() {
79         fCycles = 0ul;
80         fScanlines = 0ul;
81         fPixels = 0ul;
82     }
83 
printIncrements(const char * name,uint64_t cycles,uint64_t scanLines,uint64_t pixels)84     void printIncrements(const char* name,
85                          uint64_t cycles,
86                          uint64_t scanLines,
87                          uint64_t pixels) const {
88         SkDebugf("%s %s: cycles=%" PRIu64 "+%" PRIu64
89                        " scanlines=%" PRIu64 "+%" PRIu64 " pixels=%" PRIu64,
90                  fHeader, name,
91                  fCycles - cycles, cycles,
92                  fScanlines - scanLines, scanLines,
93                  fPixels);
94         SkDebugf("\n");
95     }
96 
printCounts(const char * name)97     void printCounts(const char* name) const {
98         SkDebugf("%s cycles: %" PRIu64 " "
99                  "   scanlines: %" PRIu64 " pixels: %" PRIu64,
100                  fHeader,
101                  fCycles,
102                  fScanlines,
103                  fPixels);
104         SkDebugf(" ");
105     }
106 
getCycles()107     uint64_t getCycles() const { return fCycles; }
getScanlines()108     uint64_t getScanlines() const { return fScanlines; }
getPixels()109     uint64_t getPixels() const { return fPixels; }
110 
111     class Step {
112     public:
Step(SkBlitterTrace * trace,const char * name,uint64_t scanlines,uint64_t pixels)113         Step(SkBlitterTrace* trace,
114              const char* name,
115              uint64_t scanlines,
116              uint64_t pixels)
117             : fTrace(trace)
118             , fName(name)
119             , fScanlines(scanlines)
120             , fPixels(pixels) {
121             fStartTime = SkCycles::Now();
122         }
add(uint64_t scanlines,uint64_t pixels)123         void add(uint64_t scanlines, uint64_t pixels) {
124             fScanlines += scanlines;
125             fPixels += pixels;
126         }
~Step()127         ~Step() {
128             if (fTrace == nullptr) {
129                 return;
130             }
131             auto endTime = SkCycles::Now() - fStartTime;
132             fTrace->addTrace(/*name=*/fName,
133                              /*cycles=*/endTime,
134                              /*scanlines=*/fScanlines,
135                              /*pixels=*/fPixels);
136         }
137     private:
138         SkBlitterTrace* fTrace = nullptr;
139         const char* fName = "";
140         uint64_t fStartTime = 0ul;
141         uint64_t fScanlines = 0ul;
142         uint64_t fPixels = 0ul;
143     };
144 
145 private:
146     const char* fHeader = "";
147     bool fTraceSteps = false;
148     uint64_t fCycles = 0ul;
149     uint64_t fScanlines = 0ul;
150     uint64_t fPixels = 0ul;
151 };
152 
153 #define SK_BLITTER_TRACE_INIT \
154 extern SkBlitterTrace gSkVMBlitterTrace;                        \
155 extern SkBlitterTrace gSkRPBlitterTrace;                        \
156                                                                 \
157 static SkBlitterTrace gSkVMBlitterTraceCapture("VM", false);  \
158 static SkBlitterTrace gSkRPBlitterTraceCapture("RP", false);
159 
160 #define SK_BLITTER_TRACE_LOCAL_SETUP \
161     gSkVMBlitterTrace.reset(); \
162     gSkRPBlitterTrace.reset()
163 
164 #define SK_BLITTER_TRACE_LOCAL_TEARDOWN \
165     gSkVMBlitterTraceCapture = gSkVMBlitterTrace; \
166     gSkRPBlitterTraceCapture = gSkRPBlitterTrace
167 
168 #define SK_BLITTER_TRACE_PRINT \
169     gSkVMBlitterTraceCapture.printCounts("Total"); \
170     SkDebugf("0 "); \
171     gSkRPBlitterTraceCapture.printCounts("Total")
172 
173 #else
174 #define SK_BLITTER_TRACE_INIT
175 #define SK_BLITTER_TRACE_LOCAL_SETUP SK_BLITTER_TRACE_NO_CODE
176 #define SK_BLITTER_TRACE_LOCAL_TEARDOWN SK_BLITTER_TRACE_NO_CODE
177 #define SK_BLITTER_TRACE_PRINT SK_BLITTER_TRACE_NO_CODE
178 #endif // SKIA_COMPARE_VM_VS_RP
179 
180 #endif // SkBlitterTraceCommon_DEFINED
181