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