• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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;
WStreamWriteTextBenchmark__anone3b05aab0111::WStreamWriteTextBenchmark26     WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anone3b05aab0111::WStreamWriteTextBenchmark27     const char* onGetName() override { return "WStreamWriteText"; }
isSuitableFor__anone3b05aab0111::WStreamWriteTextBenchmark28     bool isSuitableFor(Backend backend) override {
29         return backend == kNonRendering_Backend;
30     }
onDraw__anone3b05aab0111::WStreamWriteTextBenchmark31     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 {
PDFScalarBenchPDFScalarBench46     PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
47     const char* fName;
48     float (*fNextFloat)(SkRandom*);
isSuitableForPDFScalarBench49     bool isSuitableFor(Backend b) override {
50         return b == kNonRendering_Backend;
51     }
onGetNamePDFScalarBench52     const char* onGetName() override { return fName; }
onDrawPDFScalarBench53     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 
next_common(SkRandom * random)63 float next_common(SkRandom* random) {
64     return random->nextRangeF(-500.0f, 1500.0f);
65 }
next_any(SkRandom * random)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:
PDFImageBench()86     PDFImageBench() {}
~PDFImageBench()87     ~PDFImageBench() override {}
88 
89 protected:
onGetName()90     const char* onGetName() override { return "PDFImage"; }
isSuitableFor(Backend backend)91     bool isSuitableFor(Backend backend) override {
92         return backend == kNonRendering_Backend;
93     }
onDelayedSetup()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     }
onDraw(int loops,SkCanvas *)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:
PDFJpegImageBench()123     PDFJpegImageBench() {}
~PDFJpegImageBench()124     ~PDFJpegImageBench() override {}
125 
126 protected:
onGetName()127     const char* onGetName() override { return "PDFJpegImage"; }
isSuitableFor(Backend backend)128     bool isSuitableFor(Backend backend) override {
129         return backend == kNonRendering_Backend;
130     }
onDelayedSetup()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     }
onDraw(int loops,SkCanvas *)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:
PDFCompressionBench()160     PDFCompressionBench() {}
~PDFCompressionBench()161     ~PDFCompressionBench() override {}
162 
163 protected:
onGetName()164     const char* onGetName() override { return "PDFCompression"; }
isSuitableFor(Backend backend)165     bool isSuitableFor(Backend backend) override {
166         return backend == kNonRendering_Backend;
167     }
onDelayedSetup()168     void onDelayedSetup() override {
169         fAsset = GetResourceAsStream("pdf_command_stream.txt");
170     }
onDraw(int loops,SkCanvas *)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 {
isSuitableFor__anone3b05aab0311::PDFColorComponentBench187     bool isSuitableFor(Backend b) override {
188         return b == kNonRendering_Backend;
189     }
onGetName__anone3b05aab0311::PDFColorComponentBench190     const char* onGetName() override { return "PDFColorComponent"; }
onDraw__anone3b05aab0311::PDFColorComponentBench191     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;
onGetName__anone3b05aab0311::PDFShaderBench203     const char* onGetName() final { return "PDFShader"; }
isSuitableFor__anone3b05aab0311::PDFShaderBench204     bool isSuitableFor(Backend b) final { return b == kNonRendering_Backend; }
onDelayedSetup__anone3b05aab0311::PDFShaderBench205     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     }
onDraw__anone3b05aab0311::PDFShaderBench215     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;
WritePDFTextBenchmark__anone3b05aab0311::WritePDFTextBenchmark229     WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
onGetName__anone3b05aab0311::WritePDFTextBenchmark230     const char* onGetName() override { return "WritePDFText"; }
isSuitableFor__anone3b05aab0311::WritePDFTextBenchmark231     bool isSuitableFor(Backend backend) override {
232         return backend == kNonRendering_Backend;
233     }
onDraw__anone3b05aab0311::WritePDFTextBenchmark234     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 {
big_pdf_test(SkDocument * doc,const SkBitmap & background)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 
make_background()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;
PDFBigDocBench__anone3b05aab0411::PDFBigDocBench357     PDFBigDocBench(bool fast) : fFast(fast) {}
onDelayedSetup__anone3b05aab0411::PDFBigDocBench358     void onDelayedSetup() override {
359         fBackground = make_background();
360         fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
361     }
onGetName__anone3b05aab0411::PDFBigDocBench362     const char* onGetName() override {
363         static const char kNameFast[] = "PDFBigDocBench_fast";
364         static const char kNameSlow[] = "PDFBigDocBench_slow";
365         return fFast ? kNameFast : kNameSlow;
366     }
isSuitableFor__anone3b05aab0411::PDFBigDocBench367     bool isSuitableFor(Backend backend) override { return backend == kNonRendering_Backend; }
onDraw__anone3b05aab0411::PDFBigDocBench368     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