From b4a8a629406fd84c04ecbb1bd2301cfbff91121d Mon Sep 17 00:00:00 2001 From: Hal Canary Date: Wed, 21 Feb 2018 15:49:41 -0500 Subject: SkFloatToDecimal: optimize the less common cases. bench PDFScalar_random goes from 120 ns to 70 ns. Change-Id: I6254f5c900395ee470ffee26303915025a8f0dda Reviewed-on: https://skia-review.googlesource.com/131151 Commit-Queue: Ben Wagner Reviewed-by: Ben Wagner Auto-Submit: Hal Canary --- bench/PDFBench.cpp | 20 +++++++++++++++++--- src/utils/SkFloatToDecimal.cpp | 24 ++++++++++++++++++------ 2 files changed, 35 insertions(+), 9 deletions(-) diff --git a/bench/PDFBench.cpp b/bench/PDFBench.cpp index bebf2b9f17..4cda80bd6e 100644 --- a/bench/PDFBench.cpp +++ b/bench/PDFBench.cpp @@ -40,21 +40,35 @@ DEF_BENCH(return new WStreamWriteTextBenchmark;) // Test speed of SkFloatToDecimal for typical floats that // might be found in a PDF document. struct PDFScalarBench : public Benchmark { + PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {} + const char* fName; + float (*fNextFloat)(SkRandom*); bool isSuitableFor(Backend b) override { return b == kNonRendering_Backend; } - const char* onGetName() override { return "PDFScalar"; } + const char* onGetName() override { return fName; } void onDraw(int loops, SkCanvas*) override { SkRandom random; char dst[kMaximumSkFloatToDecimalLength]; while (loops-- > 0) { - auto f = random.nextRangeF(-500.0f, 1500.0f); + auto f = fNextFloat(&random); (void)SkFloatToDecimal(f, dst); } } }; -DEF_BENCH(return new PDFScalarBench;) +float next_common(SkRandom* random) { + return random->nextRangeF(-500.0f, 1500.0f); +} +float next_any(SkRandom* random) { + union { uint32_t u; float f; }; + u = random->nextU(); + static_assert(sizeof(float) == sizeof(uint32_t), ""); + return f; +} + +DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);) +DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);) #ifdef SK_SUPPORT_PDF diff --git a/src/utils/SkFloatToDecimal.cpp b/src/utils/SkFloatToDecimal.cpp index 273175a897..f2a155398b 100644 --- a/src/utils/SkFloatToDecimal.cpp +++ b/src/utils/SkFloatToDecimal.cpp @@ -13,6 +13,22 @@ #include "SkTypes.h" +// returns `value * pow(base, e)`, assuming `e` is positive. +static double pow_by_squaring(double value, double base, int e) { + // https://en.wikipedia.org/wiki/Exponentiation_by_squaring + SkASSERT(e > 0); + while (true) { + if (e & 1) { + value *= base; + } + e >>= 1; + if (0 == e) { + return value; + } + base *= base; + } +} + // Return pow(10.0, e), optimized for common cases. static double pow10(int e) { switch (e) { @@ -34,14 +50,10 @@ static double pow10(int e) { case 15: return 1e+15; default: if (e > 15) { - double value = 1e+15; - while (e-- > 15) { value *= 10.0; } - return value; + return pow_by_squaring(1e+15, 10.0, e - 15); } else { SkASSERT(e < 0); - double value = 1.0; - while (e++ < 0) { value /= 10.0; } - return value; + return pow_by_squaring(1.0, 0.1, -e); } } } -- cgit v1.2.3