Home | History | Annotate | Download | only in bench
      1 /*
      2  * Copyright 2016 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 
      8 #include "Benchmark.h"
      9 
     10 #include "Resources.h"
     11 #include "SkAutoPixmapStorage.h"
     12 #include "SkData.h"
     13 #include "SkGradientShader.h"
     14 #include "SkImage.h"
     15 #include "SkPixmap.h"
     16 #include "SkRandom.h"
     17 #include "SkStream.h"
     18 
     19 namespace {
     20 struct WStreamWriteTextBenchmark : public Benchmark {
     21     std::unique_ptr<SkWStream> fWStream;
     22     WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
     23     const char* onGetName() override { return "WStreamWriteText"; }
     24     bool isSuitableFor(Backend backend) override {
     25         return backend == kNonRendering_Backend;
     26     }
     27     void onDraw(int loops, SkCanvas*) override {
     28         while (loops-- > 0) {
     29             for (int i = 1000; i-- > 0;) {
     30                 fWStream->writeText("HELLO SKIA!\n");
     31             }
     32         }
     33     }
     34 };
     35 }  // namespace
     36 
     37 DEF_BENCH(return new WStreamWriteTextBenchmark;)
     38 
     39 #ifdef SK_SUPPORT_PDF
     40 
     41 #include "SkPDFBitmap.h"
     42 #include "SkPDFDocument.h"
     43 #include "SkPDFShader.h"
     44 #include "SkPDFUtils.h"
     45 
     46 namespace {
     47 static void test_pdf_object_serialization(const sk_sp<SkPDFObject> object) {
     48     // SkDebugWStream wStream;
     49     SkNullWStream wStream;
     50     SkPDFObjNumMap objNumMap;
     51     objNumMap.addObjectRecursively(object.get());
     52     for (int i = 0; i < objNumMap.objects().count(); ++i) {
     53         SkPDFObject* object = objNumMap.objects()[i].get();
     54         wStream.writeDecAsText(i + 1);
     55         wStream.writeText(" 0 obj\n");
     56         object->emitObject(&wStream, objNumMap);
     57         wStream.writeText("\nendobj\n");
     58     }
     59 }
     60 
     61 class PDFImageBench : public Benchmark {
     62 public:
     63     PDFImageBench() {}
     64     ~PDFImageBench() override {}
     65 
     66 protected:
     67     const char* onGetName() override { return "PDFImage"; }
     68     bool isSuitableFor(Backend backend) override {
     69         return backend == kNonRendering_Backend;
     70     }
     71     void onDelayedSetup() override {
     72         sk_sp<SkImage> img(GetResourceAsImage("color_wheel.png"));
     73         if (img) {
     74             // force decoding, throw away reference to encoded data.
     75             SkAutoPixmapStorage pixmap;
     76             pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
     77             if (img->readPixels(pixmap, 0, 0)) {
     78                 fImage = SkImage::MakeRasterCopy(pixmap);
     79             }
     80         }
     81     }
     82     void onDraw(int loops, SkCanvas*) override {
     83         if (!fImage) {
     84             return;
     85         }
     86         while (loops-- > 0) {
     87             auto object = SkPDFCreateBitmapObject(fImage, nullptr);
     88             SkASSERT(object);
     89             if (!object) {
     90                 return;
     91             }
     92             test_pdf_object_serialization(object);
     93         }
     94     }
     95 
     96 private:
     97     sk_sp<SkImage> fImage;
     98 };
     99 
    100 class PDFJpegImageBench : public Benchmark {
    101 public:
    102     PDFJpegImageBench() {}
    103     ~PDFJpegImageBench() override {}
    104 
    105 protected:
    106     const char* onGetName() override { return "PDFJpegImage"; }
    107     bool isSuitableFor(Backend backend) override {
    108         return backend == kNonRendering_Backend;
    109     }
    110     void onDelayedSetup() override {
    111         sk_sp<SkImage> img(GetResourceAsImage("mandrill_512_q075.jpg"));
    112         if (!img) { return; }
    113         sk_sp<SkData> encoded = img->refEncodedData();
    114         SkASSERT(encoded);
    115         if (!encoded) { return; }
    116         fImage = img;
    117     }
    118     void onDraw(int loops, SkCanvas*) override {
    119         if (!fImage) {
    120             SkDEBUGFAIL("");
    121             return;
    122         }
    123         while (loops-- > 0) {
    124             auto object = SkPDFCreateBitmapObject(fImage, nullptr);
    125             SkASSERT(object);
    126             if (!object) {
    127                 return;
    128             }
    129             test_pdf_object_serialization(object);
    130         }
    131     }
    132 
    133 private:
    134     sk_sp<SkImage> fImage;
    135 };
    136 
    137 /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
    138     alternate zlib settings, usage, and library versions. */
    139 class PDFCompressionBench : public Benchmark {
    140 public:
    141     PDFCompressionBench() {}
    142     ~PDFCompressionBench() override {}
    143 
    144 protected:
    145     const char* onGetName() override { return "PDFCompression"; }
    146     bool isSuitableFor(Backend backend) override {
    147         return backend == kNonRendering_Backend;
    148     }
    149     void onDelayedSetup() override {
    150         fAsset.reset(GetResourceAsStream("pdf_command_stream.txt"));
    151     }
    152     void onDraw(int loops, SkCanvas*) override {
    153         SkASSERT(fAsset);
    154         if (!fAsset) { return; }
    155         while (loops-- > 0) {
    156             sk_sp<SkPDFObject> object =
    157                 sk_make_sp<SkPDFSharedStream>(
    158                         std::unique_ptr<SkStreamAsset>(fAsset->duplicate()));
    159             test_pdf_object_serialization(object);
    160         }
    161     }
    162 
    163 private:
    164     std::unique_ptr<SkStreamAsset> fAsset;
    165 };
    166 
    167 // Test speed of SkPDFUtils::FloatToDecimal for typical floats that
    168 // might be found in a PDF document.
    169 struct PDFScalarBench : public Benchmark {
    170     bool isSuitableFor(Backend b) override {
    171         return b == kNonRendering_Backend;
    172     }
    173     const char* onGetName() override { return "PDFScalar"; }
    174     void onDraw(int loops, SkCanvas*) override {
    175         SkRandom random;
    176         char dst[SkPDFUtils::kMaximumFloatDecimalLength];
    177         while (loops-- > 0) {
    178             auto f = random.nextRangeF(-500.0f, 1500.0f);
    179             (void)SkPDFUtils::FloatToDecimal(f, dst);
    180         }
    181     }
    182 };
    183 
    184 struct PDFColorComponentBench : public Benchmark {
    185     bool isSuitableFor(Backend b) override {
    186         return b == kNonRendering_Backend;
    187     }
    188     const char* onGetName() override { return "PDFColorComponent"; }
    189     void onDraw(int loops, SkCanvas*) override {
    190         char dst[5];
    191         while (loops-- > 0) {
    192             for (int i = 0; i < 256; ++i) {
    193                 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
    194             }
    195         }
    196     }
    197 };
    198 
    199 struct PDFShaderBench : public Benchmark {
    200     sk_sp<SkShader> fShader;
    201     const char* onGetName() final { return "PDFShader"; }
    202     bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
    203     void onDelayedSetup() final {
    204         const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
    205         const SkColor colors[] = {
    206             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
    207             SK_ColorWHITE, SK_ColorBLACK,
    208         };
    209         fShader = SkGradientShader::MakeLinear(
    210                 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
    211                 SkShader::kClamp_TileMode);
    212     }
    213     void onDraw(int loops, SkCanvas*) final {
    214         SkASSERT(fShader);
    215         while (loops-- > 0) {
    216             SkNullWStream nullStream;
    217             SkPDFDocument doc(&nullStream, nullptr, 72,
    218                               SkDocument::PDFMetadata(), nullptr, false);
    219             sk_sp<SkPDFObject> shader =
    220                     SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(), {0, 0, 400,400});
    221         }
    222     }
    223 };
    224 
    225 struct WritePDFTextBenchmark : public Benchmark {
    226     std::unique_ptr<SkWStream> fWStream;
    227     WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
    228     const char* onGetName() override { return "WritePDFText"; }
    229     bool isSuitableFor(Backend backend) override {
    230         return backend == kNonRendering_Backend;
    231     }
    232     void onDraw(int loops, SkCanvas*) override {
    233         static const char kHello[] = "HELLO SKIA!\n";
    234         static const char kBinary[] = "\001\002\003\004\005\006";
    235         while (loops-- > 0) {
    236             for (int i = 1000; i-- > 0;) {
    237                 SkPDFUtils::WriteString(fWStream.get(), kHello, strlen(kHello));
    238                 SkPDFUtils::WriteString(fWStream.get(), kBinary, strlen(kBinary));
    239             }
    240         }
    241     }
    242 };
    243 
    244 }  // namespace
    245 DEF_BENCH(return new PDFImageBench;)
    246 DEF_BENCH(return new PDFJpegImageBench;)
    247 DEF_BENCH(return new PDFCompressionBench;)
    248 DEF_BENCH(return new PDFScalarBench;)
    249 DEF_BENCH(return new PDFColorComponentBench;)
    250 DEF_BENCH(return new PDFShaderBench;)
    251 DEF_BENCH(return new WritePDFTextBenchmark;)
    252 
    253 #endif
    254 
    255