blob: b4adb5ce779c35be79ab50830e048605c0843334 [file] [log] [blame]
/*
* Copyright 2022 Google Inc.
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*
* This is an experimental (and probably temporary) solution that allows
* to compare performance SkVM blitters vs RasterPipeline blitters.
* In addition to measuring performance (which is questionable) it also produces
* other counts (pixels, scanlines) and more detailed traces that
* can explain the current results (SkVM is slower) and help improve it.
* The entire code is hidden under build flag skia_compare_vm_vs_rp=true
* and will not appear at all without it.
*/
#ifndef SkBlitterTraceCommon_DEFINED
#define SkBlitterTraceCommon_DEFINED
#include <inttypes.h>
#include <unordered_map>
#define SK_BLITTER_TRACE_NO_CODE do {} while (0)
#ifdef SKIA_COMPARE_VM_VS_RP
#include "src/utils/SkCycles.h"
class SkBlitterTrace {
/*
* This class collects information for RasterPipeLine vs SkVM
* performance comparison.
* How to get the comparison table:
* 1. Add to your Release/args.gn an argument: skia_compare_vm_vs_rp=true
* Build nanobench.
* 2. Run nanobench for SkVM:
* []/Release/nanobench
* --csv --config 8888 --skvm --loops 100 --samples 1
* --match $(ls skps | grep --invert-match svg ) 2>&1 | tee VM.data
* 3. Run nanobench for RasterPipeLine:
* []/Release/nanobench
* --csv --config 8888 --forceRasterPipeline --loops 100
* --samples 1 --match $(ls skps | grep --invert-match svg )
* 2>&1 | tee RP.data
* 4. Extract the information side-by-side:
* awk 'BEGIN {OFS=","; fileNum = 0} ($2 ~ /MB/) && fileNum == 0
* {vmvmcycles[$3] = $6; vmvmscan[$3] = $8; vmvmpixels[$3] = $10;
* vmvminterp[$3] = $11; vmrpcycle[$3] = $14; vmrpscan[$3] = $16;
* vmrppixels[$3] = $18} ($2 ~ /MB/) && fileNum == 1 {print $3,
* vmvmcycles[$3], vmvmscan[$3], vmvmpixels[$3], vmvminterp[$3], $6, $8,
* $10, $11, $14, $16, $18} ENDFILE {fileNum += 1}'
* VM.data RP.data > compare.csv
* 5. Open the compare.csv table in Google Spreadsheets.
* You will get columns [A:P]. Add 4 more columns with formulas:
* Q: =B/M-1
* R: =N-C
* S: =O-D
* T: =2*(S<>0)+(R<>0)
* To be honest R, S, T columns are here for checking only (they all
* supposed to have zero values in them)
* Column Q shows the actual performance difference. Negative value means
* that wins SkVM, positive - RasterPipeLine.
*/
public:
SkBlitterTrace(const char* header, bool traceSteps = false)
: fHeader(header), fTraceSteps(traceSteps) { }
SkBlitterTrace& operator= (const SkBlitterTrace&) = default;
void addTrace(const char* name, uint64_t cycles, uint64_t scanLines, uint64_t pixels) {
fCycles += cycles;
fScanlines += scanLines;
fPixels += pixels;
if (fTraceSteps) {
printIncrements(name, cycles, scanLines, pixels);
}
}
void reset() {
fCycles = 0ul;
fScanlines = 0ul;
fPixels = 0ul;
}
void printIncrements(const char* name,
uint64_t cycles,
uint64_t scanLines,
uint64_t pixels) const {
SkDebugf("%s %s: cycles=%" PRIu64 "+%" PRIu64
" scanlines=%" PRIu64 "+%" PRIu64 " pixels=%" PRIu64,
fHeader, name,
fCycles - cycles, cycles,
fScanlines - scanLines, scanLines,
fPixels);
SkDebugf("\n");
}
void printCounts(const char* name) const {
SkDebugf("%s cycles: %" PRIu64 " "
" scanlines: %" PRIu64 " pixels: %" PRIu64,
fHeader,
fCycles,
fScanlines,
fPixels);
SkDebugf(" ");
}
uint64_t getCycles() const { return fCycles; }
uint64_t getScanlines() const { return fScanlines; }
uint64_t getPixels() const { return fPixels; }
class Step {
public:
Step(SkBlitterTrace* trace,
const char* name,
uint64_t scanlines,
uint64_t pixels)
: fTrace(trace)
, fName(name)
, fScanlines(scanlines)
, fPixels(pixels) {
fStartTime = SkCycles::Now();
}
void add(uint64_t scanlines, uint64_t pixels) {
fScanlines += scanlines;
fPixels += pixels;
}
~Step() {
if (fTrace == nullptr) {
return;
}
auto endTime = SkCycles::Now() - fStartTime;
fTrace->addTrace(/*name=*/fName,
/*cycles=*/endTime,
/*scanlines=*/fScanlines,
/*pixels=*/fPixels);
}
private:
SkBlitterTrace* fTrace = nullptr;
const char* fName = "";
uint64_t fStartTime = 0ul;
uint64_t fScanlines = 0ul;
uint64_t fPixels = 0ul;
};
private:
const char* fHeader = "";
bool fTraceSteps = false;
uint64_t fCycles = 0ul;
uint64_t fScanlines = 0ul;
uint64_t fPixels = 0ul;
};
#define SK_BLITTER_TRACE_INIT \
extern SkBlitterTrace gSkVMBlitterTrace; \
extern SkBlitterTrace gSkRPBlitterTrace; \
\
static SkBlitterTrace gSkVMBlitterTraceCapture("VM", false); \
static SkBlitterTrace gSkRPBlitterTraceCapture("RP", false);
#define SK_BLITTER_TRACE_LOCAL_SETUP \
gSkVMBlitterTrace.reset(); \
gSkRPBlitterTrace.reset()
#define SK_BLITTER_TRACE_LOCAL_TEARDOWN \
gSkVMBlitterTraceCapture = gSkVMBlitterTrace; \
gSkRPBlitterTraceCapture = gSkRPBlitterTrace
#define SK_BLITTER_TRACE_PRINT \
gSkVMBlitterTraceCapture.printCounts("Total"); \
SkDebugf("0 "); \
gSkRPBlitterTraceCapture.printCounts("Total")
#else
#define SK_BLITTER_TRACE_INIT
#define SK_BLITTER_TRACE_LOCAL_SETUP SK_BLITTER_TRACE_NO_CODE
#define SK_BLITTER_TRACE_LOCAL_TEARDOWN SK_BLITTER_TRACE_NO_CODE
#define SK_BLITTER_TRACE_PRINT SK_BLITTER_TRACE_NO_CODE
#endif // SKIA_COMPARE_VM_VS_RP
#endif // SkBlitterTraceCommon_DEFINED