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 "SkExecutor.h"
     14 #include "SkFloatToDecimal.h"
     15 #include "SkGradientShader.h"
     16 #include "SkImage.h"
     17 #include "SkPDFUnion.h"
     18 #include "SkPixmap.h"
     19 #include "SkRandom.h"
     20 #include "SkStream.h"
     21 #include "SkTo.h"
     22 
     23 namespace {
     24 struct WStreamWriteTextBenchmark : public Benchmark {
     25     std::unique_ptr<SkWStream> fWStream;
     26     WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
     27     const char* onGetName() override { return "WStreamWriteText"; }
     28     bool isSuitableFor(Backend backend) override {
     29         return backend == kNonRendering_Backend;
     30     }
     31     void onDraw(int loops, SkCanvas*) override {
     32         while (loops-- > 0) {
     33             for (int i = 1000; i-- > 0;) {
     34                 fWStream->writeText("HELLO SKIA!\n");
     35             }
     36         }
     37     }
     38 };
     39 }  // namespace
     40 
     41 DEF_BENCH(return new WStreamWriteTextBenchmark;)
     42 
     43 // Test speed of SkFloatToDecimal for typical floats that
     44 // might be found in a PDF document.
     45 struct PDFScalarBench : public Benchmark {
     46     PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
     47     const char* fName;
     48     float (*fNextFloat)(SkRandom*);
     49     bool isSuitableFor(Backend b) override {
     50         return b == kNonRendering_Backend;
     51     }
     52     const char* onGetName() override { return fName; }
     53     void onDraw(int loops, SkCanvas*) override {
     54         SkRandom random;
     55         char dst[kMaximumSkFloatToDecimalLength];
     56         while (loops-- > 0) {
     57             auto f = fNextFloat(&random);
     58             (void)SkFloatToDecimal(f, dst);
     59         }
     60     }
     61 };
     62 
     63 float next_common(SkRandom* random) {
     64     return random->nextRangeF(-500.0f, 1500.0f);
     65 }
     66 float next_any(SkRandom* random) {
     67     union { uint32_t u; float f; };
     68     u = random->nextU();
     69     static_assert(sizeof(float) == sizeof(uint32_t), "");
     70     return f;
     71 }
     72 
     73 DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
     74 DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)
     75 
     76 #ifdef SK_SUPPORT_PDF
     77 
     78 #include "SkPDFBitmap.h"
     79 #include "SkPDFDocumentPriv.h"
     80 #include "SkPDFShader.h"
     81 #include "SkPDFUtils.h"
     82 
     83 namespace {
     84 class PDFImageBench : public Benchmark {
     85 public:
     86     PDFImageBench() {}
     87     ~PDFImageBench() override {}
     88 
     89 protected:
     90     const char* onGetName() override { return "PDFImage"; }
     91     bool isSuitableFor(Backend backend) override {
     92         return backend == kNonRendering_Backend;
     93     }
     94     void onDelayedSetup() override {
     95         sk_sp<SkImage> img(GetResourceAsImage("images/color_wheel.png"));
     96         if (img) {
     97             // force decoding, throw away reference to encoded data.
     98             SkAutoPixmapStorage pixmap;
     99             pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
    100             if (img->readPixels(pixmap, 0, 0)) {
    101                 fImage = SkImage::MakeRasterCopy(pixmap);
    102             }
    103         }
    104     }
    105     void onDraw(int loops, SkCanvas*) override {
    106         if (!fImage) {
    107             return;
    108         }
    109         while (loops-- > 0) {
    110             SkNullWStream nullStream;
    111             SkPDFDocument doc(&nullStream, SkPDF::Metadata());
    112             doc.beginPage(256, 256);
    113             (void)SkPDFSerializeImage(fImage.get(), &doc);
    114         }
    115     }
    116 
    117 private:
    118     sk_sp<SkImage> fImage;
    119 };
    120 
    121 class PDFJpegImageBench : public Benchmark {
    122 public:
    123     PDFJpegImageBench() {}
    124     ~PDFJpegImageBench() override {}
    125 
    126 protected:
    127     const char* onGetName() override { return "PDFJpegImage"; }
    128     bool isSuitableFor(Backend backend) override {
    129         return backend == kNonRendering_Backend;
    130     }
    131     void onDelayedSetup() override {
    132         sk_sp<SkImage> img(GetResourceAsImage("images/mandrill_512_q075.jpg"));
    133         if (!img) { return; }
    134         sk_sp<SkData> encoded = img->refEncodedData();
    135         SkASSERT(encoded);
    136         if (!encoded) { return; }
    137         fImage = img;
    138     }
    139     void onDraw(int loops, SkCanvas*) override {
    140         if (!fImage) {
    141             SkDEBUGFAIL("");
    142             return;
    143         }
    144         while (loops-- > 0) {
    145             SkNullWStream nullStream;
    146             SkPDFDocument doc(&nullStream, SkPDF::Metadata());
    147             doc.beginPage(256, 256);
    148             (void)SkPDFSerializeImage(fImage.get(), &doc);
    149         }
    150     }
    151 
    152 private:
    153     sk_sp<SkImage> fImage;
    154 };
    155 
    156 /** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
    157     alternate zlib settings, usage, and library versions. */
    158 class PDFCompressionBench : public Benchmark {
    159 public:
    160     PDFCompressionBench() {}
    161     ~PDFCompressionBench() override {}
    162 
    163 protected:
    164     const char* onGetName() override { return "PDFCompression"; }
    165     bool isSuitableFor(Backend backend) override {
    166         return backend == kNonRendering_Backend;
    167     }
    168     void onDelayedSetup() override {
    169         fAsset = GetResourceAsStream("pdf_command_stream.txt");
    170     }
    171     void onDraw(int loops, SkCanvas*) override {
    172         SkASSERT(fAsset);
    173         if (!fAsset) { return; }
    174         while (loops-- > 0) {
    175             SkNullWStream wStream;
    176             SkPDFDocument doc(&wStream, SkPDF::Metadata());
    177             doc.beginPage(256, 256);
    178             (void)SkPDFStreamOut(nullptr, fAsset->duplicate(), &doc, true);
    179        }
    180     }
    181 
    182 private:
    183     std::unique_ptr<SkStreamAsset> fAsset;
    184 };
    185 
    186 struct PDFColorComponentBench : public Benchmark {
    187     bool isSuitableFor(Backend b) override {
    188         return b == kNonRendering_Backend;
    189     }
    190     const char* onGetName() override { return "PDFColorComponent"; }
    191     void onDraw(int loops, SkCanvas*) override {
    192         char dst[5];
    193         while (loops-- > 0) {
    194             for (int i = 0; i < 256; ++i) {
    195                 (void)SkPDFUtils::ColorToDecimal(SkToU8(i), dst);
    196             }
    197         }
    198     }
    199 };
    200 
    201 struct PDFShaderBench : public Benchmark {
    202     sk_sp<SkShader> fShader;
    203     const char* onGetName() final { return "PDFShader"; }
    204     bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
    205     void onDelayedSetup() final {
    206         const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
    207         const SkColor colors[] = {
    208             SK_ColorRED, SK_ColorGREEN, SK_ColorBLUE,
    209             SK_ColorWHITE, SK_ColorBLACK,
    210         };
    211         fShader = SkGradientShader::MakeLinear(
    212                 pts, colors, nullptr, SK_ARRAY_COUNT(colors),
    213                 SkShader::kClamp_TileMode);
    214     }
    215     void onDraw(int loops, SkCanvas*) final {
    216         SkASSERT(fShader);
    217         while (loops-- > 0) {
    218             SkNullWStream nullStream;
    219             SkPDFDocument doc(&nullStream, SkPDF::Metadata());
    220             doc.beginPage(256, 256);
    221             (void) SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
    222                                    {0, 0, 400, 400}, SK_ColorBLACK);
    223         }
    224     }
    225 };
    226 
    227 struct WritePDFTextBenchmark : public Benchmark {
    228     std::unique_ptr<SkWStream> fWStream;
    229     WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
    230     const char* onGetName() override { return "WritePDFText"; }
    231     bool isSuitableFor(Backend backend) override {
    232         return backend == kNonRendering_Backend;
    233     }
    234     void onDraw(int loops, SkCanvas*) override {
    235         static const char kHello[] = "HELLO SKIA!\n";
    236         static const char kBinary[] = "\001\002\003\004\005\006";
    237         while (loops-- > 0) {
    238             for (int i = 1000; i-- > 0;) {
    239                 SkPDFWriteString(fWStream.get(), kHello, strlen(kHello));
    240                 SkPDFWriteString(fWStream.get(), kBinary, strlen(kBinary));
    241             }
    242         }
    243     }
    244 };
    245 
    246 }  // namespace
    247 DEF_BENCH(return new PDFImageBench;)
    248 DEF_BENCH(return new PDFJpegImageBench;)
    249 DEF_BENCH(return new PDFCompressionBench;)
    250 DEF_BENCH(return new PDFColorComponentBench;)
    251 DEF_BENCH(return new PDFShaderBench;)
    252 DEF_BENCH(return new WritePDFTextBenchmark;)
    253 
    254 #ifdef SK_PDF_ENABLE_SLOW_TESTS
    255 #include "SkExecutor.h"
    256 namespace {
    257 void big_pdf_test(SkDocument* doc, const SkBitmap& background) {
    258     static const char* kText[] = {
    259         "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do",
    260         "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
    261         "minim veniam, quis nostrud exercitation ullamco laboris nisi ut",
    262         "aliquip ex ea commodo consequat. Duis aute irure dolor in",
    263         "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla",
    264         "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in",
    265         "culpa qui officia deserunt mollit anim id est laborum.",
    266         "",
    267         "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
    268         "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
    269         "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
    270         "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
    271         "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
    272         "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
    273         "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
    274         "sed quia non numquam do eius modi tempora incididunt, ut labore et",
    275         "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
    276         "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
    277         "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
    278         "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
    279         "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
    280         "pariatur?",
    281         "",
    282         "At vero eos et accusamus et iusto odio dignissimos ducimus, qui",
    283         "blanditiis praesentium voluptatum deleniti atque corrupti, quos",
    284         "dolores et quas molestias excepturi sint, obcaecati cupiditate non",
    285         "provident, similique sunt in culpa, qui officia deserunt mollitia",
    286         "animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis",
    287         "est et expedita distinctio. Nam libero tempore, cum soluta nobis est",
    288         "eligendi optio, cumque nihil impedit, quo minus id, quod maxime",
    289         "placeat, facere possimus, omnis voluptas assumenda est, omnis dolor",
    290         "repellendus. Temporibus autem quibusdam et aut officiis debitis aut",
    291         "rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint",
    292         "et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente",
    293         "delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut",
    294         "perferendis doloribus asperiores repellat",
    295         "",
    296         "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
    297         "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
    298         "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
    299         "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
    300         "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
    301         "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
    302         "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
    303         "sed quia non numquam do eius modi tempora incididunt, ut labore et",
    304         "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
    305         "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
    306         "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
    307         "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
    308         "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
    309         "pariatur?",
    310         "",
    311     };
    312     SkCanvas* canvas = nullptr;
    313     float x = 36;
    314     float y = 36;
    315     constexpr size_t kLineCount = SK_ARRAY_COUNT(kText);
    316     constexpr int kLoopCount = 200;
    317     SkFont font;
    318     SkPaint paint;
    319     for (int loop = 0; loop < kLoopCount; ++loop) {
    320         for (size_t line = 0; line < kLineCount; ++line) {
    321             y += font.getSpacing();
    322             if (!canvas || y > 792 - 36) {
    323                 y = 36 + font.getSpacing();
    324                 canvas = doc->beginPage(612, 792);
    325                 background.notifyPixelsChanged();
    326                 canvas->drawBitmap(background, 0, 0);
    327             }
    328             canvas->drawString(kText[line], x, y, font, paint);
    329         }
    330     }
    331 }
    332 
    333 SkBitmap make_background() {
    334     SkBitmap background;
    335     SkBitmap bitmap;
    336     bitmap.allocN32Pixels(32, 32);
    337     bitmap.eraseColor(SK_ColorWHITE);
    338     SkCanvas tmp(bitmap);
    339     SkPaint gray;
    340     gray.setColor(SkColorSetARGB(0xFF, 0xEE, 0xEE, 0xEE));
    341     tmp.drawRect({0,0,16,16}, gray);
    342     tmp.drawRect({16,16,32,32}, gray);
    343     SkPaint shader;
    344     shader.setShader(
    345             SkShader::MakeBitmapShader(
    346                 bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
    347     background.allocN32Pixels(612, 792);
    348     SkCanvas tmp2(background);
    349     tmp2.drawPaint(shader);
    350     return background;
    351 }
    352 
    353 struct PDFBigDocBench : public Benchmark {
    354     bool fFast;
    355     SkBitmap fBackground;
    356     std::unique_ptr<SkExecutor> fExecutor;
    357     PDFBigDocBench(bool fast) : fFast(fast) {}
    358     void onDelayedSetup() override {
    359         fBackground = make_background();
    360         fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
    361     }
    362     const char* onGetName() override {
    363         static const char kNameFast[] = "PDFBigDocBench_fast";
    364         static const char kNameSlow[] = "PDFBigDocBench_slow";
    365         return fFast ? kNameFast : kNameSlow;
    366     }
    367     bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
    368     void onDraw(int loops, SkCanvas*) override {
    369         while (loops-- > 0) {
    370             #ifdef SK_PDF_TEST_BIGDOCBENCH_OUTPUT
    371             SkFILEWStream wStream("/tmp/big_pdf.pdf");
    372             #else
    373             SkNullWStream wStream;
    374             #endif
    375             SkPDF::Metadata metadata;
    376             metadata.fExecutor = fExecutor.get();
    377             auto doc = SkPDF::MakeDocument(&wStream, metadata);
    378             big_pdf_test(doc.get(), fBackground);
    379         }
    380     }
    381 };
    382 }  // namespace
    383 DEF_BENCH(return new PDFBigDocBench(false);)
    384 DEF_BENCH(return new PDFBigDocBench(true);)
    385 #endif
    386 
    387 #endif // SK_SUPPORT_PDF
    388