Flutter Engine
The Flutter Engine
PDFBench.cpp
Go to the documentation of this file.
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 "bench/Benchmark.h"
9
11#include "include/core/SkData.h"
14#include "include/core/SkPath.h"
19#include "src/base/SkRandom.h"
21#include "src/pdf/SkPDFUnion.h"
23#include "tools/DecodeUtils.h"
24#include "tools/Resources.h"
26
27namespace {
28struct WStreamWriteTextBenchmark : public Benchmark {
29 std::unique_ptr<SkWStream> fWStream;
30 WStreamWriteTextBenchmark() : fWStream(new SkNullWStream) {}
31 const char* onGetName() override { return "WStreamWriteText"; }
32 bool isSuitableFor(Backend backend) override {
34 }
35 void onDraw(int loops, SkCanvas*) override {
36 while (loops-- > 0) {
37 for (int i = 1000; i-- > 0;) {
38 fWStream->writeText("HELLO SKIA!\n");
39 }
40 }
41 }
42};
43} // namespace
44
45DEF_BENCH(return new WStreamWriteTextBenchmark;)
46
47// Test speed of SkFloatToDecimal for typical floats that
48// might be found in a PDF document.
49struct PDFScalarBench : public Benchmark {
50 PDFScalarBench(const char* n, float (*f)(SkRandom*)) : fName(n), fNextFloat(f) {}
51 const char* fName;
52 float (*fNextFloat)(SkRandom*);
53 bool isSuitableFor(Backend b) override {
54 return b == Backend::kNonRendering;
55 }
56 const char* onGetName() override { return fName; }
57 void onDraw(int loops, SkCanvas*) override {
58 SkRandom random;
60 while (loops-- > 0) {
61 auto f = fNextFloat(&random);
62 (void)SkFloatToDecimal(f, dst);
63 }
64 }
65};
66
67float next_common(SkRandom* random) {
68 return random->nextRangeF(-500.0f, 1500.0f);
69}
70float next_any(SkRandom* random) {
71 union { uint32_t u; float f; };
72 u = random->nextU();
73 static_assert(sizeof(float) == sizeof(uint32_t), "");
74 return f;
75}
76
77DEF_BENCH(return new PDFScalarBench("PDFScalar_common", next_common);)
78DEF_BENCH(return new PDFScalarBench("PDFScalar_random", next_any);)
79
80#ifdef SK_SUPPORT_PDF
81
82#include "src/pdf/SkPDFBitmap.h"
83#include "src/pdf/SkPDFDocumentPriv.h"
84#include "src/pdf/SkPDFShader.h"
85#include "src/pdf/SkPDFUtils.h"
86
87namespace {
88class PDFImageBench : public Benchmark {
89public:
90 PDFImageBench() {}
91 ~PDFImageBench() override {}
92
93protected:
94 const char* onGetName() override { return "PDFImage"; }
95 bool isSuitableFor(Backend backend) override {
97 }
98 void onDelayedSetup() override {
99 sk_sp<SkImage> img(ToolUtils::GetResourceAsImage("images/color_wheel.png"));
100 if (img) {
101 // force decoding, throw away reference to encoded data.
102 SkAutoPixmapStorage pixmap;
103 pixmap.alloc(SkImageInfo::MakeN32Premul(img->dimensions()));
104 if (img->readPixels(nullptr, pixmap, 0, 0)) {
105 fImage = SkImages::RasterFromPixmapCopy(pixmap);
106 }
107 }
108 }
109 void onDraw(int loops, SkCanvas*) override {
110 if (!fImage) {
111 return;
112 }
113 while (loops-- > 0) {
114 SkNullWStream nullStream;
115 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
116 doc.beginPage(256, 256);
117 (void)SkPDFSerializeImage(fImage.get(), &doc);
118 }
119 }
120
121private:
122 sk_sp<SkImage> fImage;
123};
124
125class PDFJpegImageBench : public Benchmark {
126public:
127 PDFJpegImageBench() {}
128 ~PDFJpegImageBench() override {}
129
130protected:
131 const char* onGetName() override { return "PDFJpegImage"; }
132 bool isSuitableFor(Backend backend) override {
134 }
135 void onDelayedSetup() override {
136 sk_sp<SkImage> img(ToolUtils::GetResourceAsImage("images/mandrill_512_q075.jpg"));
137 if (!img) { return; }
138 sk_sp<SkData> encoded = img->refEncodedData();
139 SkASSERT(encoded);
140 if (!encoded) { return; }
141 fImage = img;
142 }
143 void onDraw(int loops, SkCanvas*) override {
144 if (!fImage) {
145 SkDEBUGFAIL("");
146 return;
147 }
148 while (loops-- > 0) {
149 SkNullWStream nullStream;
150 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
151 doc.beginPage(256, 256);
152 (void)SkPDFSerializeImage(fImage.get(), &doc);
153 }
154 }
155
156private:
157 sk_sp<SkImage> fImage;
158};
159
160/** Test calling DEFLATE on a 78k PDF command stream. Used for measuring
161 alternate zlib settings, usage, and library versions. */
162class PDFCompressionBench : public Benchmark {
163public:
164 PDFCompressionBench() {}
165 ~PDFCompressionBench() override {}
166
167protected:
168 const char* onGetName() override { return "PDFCompression"; }
169 bool isSuitableFor(Backend backend) override {
171 }
172 void onDelayedSetup() override {
173 fAsset = GetResourceAsStream("pdf_command_stream.txt");
174 }
175 void onDraw(int loops, SkCanvas*) override {
176 SkASSERT(fAsset);
177 if (!fAsset) { return; }
178 while (loops-- > 0) {
179 SkNullWStream wStream;
180 SkPDFDocument doc(&wStream, SkPDF::Metadata());
181 doc.beginPage(256, 256);
182 (void)SkPDFStreamOut(nullptr, fAsset->duplicate(),
184 }
185 }
186
187private:
188 std::unique_ptr<SkStreamAsset> fAsset;
189};
190
191struct PDFColorComponentBench : public Benchmark {
192 bool isSuitableFor(Backend b) override {
193 return b == Backend::kNonRendering;
194 }
195 const char* onGetName() override { return "PDFColorComponent"; }
196 void onDraw(int loops, SkCanvas*) override {
197 char dst[5];
198 while (loops-- > 0) {
199 for (int i = 0; i < 256; ++i) {
201 }
202 }
203 }
204};
205
206struct PDFShaderBench : public Benchmark {
207 sk_sp<SkShader> fShader;
208 const char* onGetName() final { return "PDFShader"; }
209 bool isSuitableFor(Backend b) final { return b == Backend::kNonRendering; }
210 void onDelayedSetup() final {
211 const SkPoint pts[2] = {{0.0f, 0.0f}, {100.0f, 100.0f}};
212 const SkColor colors[] = {
215 };
217 pts, colors, nullptr, std::size(colors),
219 }
220 void onDraw(int loops, SkCanvas*) final {
221 SkASSERT(fShader);
222 while (loops-- > 0) {
223 SkNullWStream nullStream;
224 SkPDFDocument doc(&nullStream, SkPDF::Metadata());
225 doc.beginPage(256, 256);
226 (void) SkPDFMakeShader(&doc, fShader.get(), SkMatrix::I(),
227 {0, 0, 400, 400}, SkColors::kBlack);
228 }
229 }
230};
231
232struct WritePDFTextBenchmark : public Benchmark {
233 std::unique_ptr<SkWStream> fWStream;
234 WritePDFTextBenchmark() : fWStream(new SkNullWStream) {}
235 const char* onGetName() override { return "WritePDFText"; }
236 bool isSuitableFor(Backend backend) override {
238 }
239 void onDraw(int loops, SkCanvas*) override {
240 static const char kHello[] = "HELLO SKIA!\n";
241 static const char kBinary[] = "\001\002\003\004\005\006";
242 while (loops-- > 0) {
243 for (int i = 1000; i-- > 0;) {
244 SkPDFWriteTextString(fWStream.get(), kHello, strlen(kHello));
245 SkPDFWriteByteString(fWStream.get(), kBinary, strlen(kBinary));
246 }
247 }
248 }
249};
250
251// Test for regression chromium:947381
252// with 5c83ae81aa : 2364.99 microsec
253// without 5c83ae81aa : 302821.78 microsec
254struct PDFClipPathBenchmark : public Benchmark {
256 void onDelayedSetup() override {
258 bitmap.allocN32Pixels(256, 256);
259 bitmap.eraseColor(SK_ColorWHITE);
260 {
261 SkCanvas tmp(bitmap);
263 paint.setAntiAlias(false);
265 paint.setStrokeWidth(10);
266 for (int r : {20, 40, 60, 80, 100, 120}) {
267 tmp.drawCircle(128, 128, (float)r, paint);
268 }
269 }
270 fPath.reset();
271 for (int y = 0; y < 256; ++y) {
272 SkColor current = bitmap.getColor(0, y);
273 int start = 0;
274 for (int x = 0; x < 256; ++x) {
275 SkColor color = bitmap.getColor(x, y);
276 if (color == current) {
277 continue;
278 }
279 if (color == SK_ColorBLACK) {
280 start = x;
281 } else {
283 }
284 current = color;
285 }
286 if (current == SK_ColorBLACK) {
287 fPath.addRect(SkRect::Make(SkIRect{start, y, 256, y + 1}));
288 }
289 }
290 }
291 const char* onGetName() override { return "PDFClipPath"; }
292 bool isSuitableFor(Backend backend) override {
294 }
295 void onDraw(int loops, SkCanvas*) override {
296 while (loops-- > 0) {
297 SkNullWStream wStream;
298 SkPDFDocument doc(&wStream, SkPDF::Metadata());
299 SkCanvas* canvas = doc.beginPage(256, 256);
300 canvas->clipPath(fPath);
301 canvas->translate(4.0f/3, 4.0f/3);
302 canvas->clipPath(fPath);
303 canvas->clear(SK_ColorRED);
304 doc.endPage();
305 }
306 }
307};
308
309} // namespace
310DEF_BENCH(return new PDFImageBench;)
311DEF_BENCH(return new PDFJpegImageBench;)
312DEF_BENCH(return new PDFCompressionBench;)
313DEF_BENCH(return new PDFColorComponentBench;)
314DEF_BENCH(return new PDFShaderBench;)
315DEF_BENCH(return new WritePDFTextBenchmark;)
316DEF_BENCH(return new PDFClipPathBenchmark;)
317
318#ifdef SK_PDF_ENABLE_SLOW_TESTS
319#include "include/core/SkExecutor.h"
320namespace {
321void big_pdf_test(SkDocument* doc, const SkBitmap& background) {
322 static const char* kText[] = {
323 "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do",
324 "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad",
325 "minim veniam, quis nostrud exercitation ullamco laboris nisi ut",
326 "aliquip ex ea commodo consequat. Duis aute irure dolor in",
327 "reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla",
328 "pariatur. Excepteur sint occaecat cupidatat non proident, sunt in",
329 "culpa qui officia deserunt mollit anim id est laborum.",
330 "",
331 "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
332 "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
333 "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
334 "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
335 "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
336 "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
337 "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
338 "sed quia non numquam do eius modi tempora incididunt, ut labore et",
339 "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
340 "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
341 "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
342 "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
343 "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
344 "pariatur?",
345 "",
346 "At vero eos et accusamus et iusto odio dignissimos ducimus, qui",
347 "blanditiis praesentium voluptatum deleniti atque corrupti, quos",
348 "dolores et quas molestias excepturi sint, obcaecati cupiditate non",
349 "provident, similique sunt in culpa, qui officia deserunt mollitia",
350 "animi, id est laborum et dolorum fuga. Et harum quidem rerum facilis",
351 "est et expedita distinctio. Nam libero tempore, cum soluta nobis est",
352 "eligendi optio, cumque nihil impedit, quo minus id, quod maxime",
353 "placeat, facere possimus, omnis voluptas assumenda est, omnis dolor",
354 "repellendus. Temporibus autem quibusdam et aut officiis debitis aut",
355 "rerum necessitatibus saepe eveniet, ut et voluptates repudiandae sint",
356 "et molestiae non recusandae. Itaque earum rerum hic tenetur a sapiente",
357 "delectus, ut aut reiciendis voluptatibus maiores alias consequatur aut",
358 "perferendis doloribus asperiores repellat",
359 "",
360 "Sed ut perspiciatis, unde omnis iste natus error sit voluptatem",
361 "accusantium doloremque laudantium, totam rem aperiam eaque ipsa, quae",
362 "ab illo inventore veritatis et quasi architecto beatae vitae dicta",
363 "sunt, explicabo. Nemo enim ipsam voluptatem, quia voluptas sit,",
364 "aspernatur aut odit aut fugit, sed quia consequuntur magni dolores",
365 "eos, qui ratione voluptatem sequi nesciunt, neque porro quisquam est,",
366 "qui dolorem ipsum, quia dolor sit amet consectetur adipiscing velit,",
367 "sed quia non numquam do eius modi tempora incididunt, ut labore et",
368 "dolore magnam aliquam quaerat voluptatem. Ut enim ad minima veniam,",
369 "quis nostrum exercitationem ullam corporis suscipit laboriosam, nisi",
370 "ut aliquid ex ea commodi consequatur? Quis autem vel eum iure",
371 "reprehenderit, qui in ea voluptate velit esse, quam nihil molestiae",
372 "consequatur, vel illum, qui dolorem eum fugiat, quo voluptas nulla",
373 "pariatur?",
374 "",
375 };
376 SkCanvas* canvas = nullptr;
377 float x = 36;
378 float y = 36;
379 constexpr size_t kLineCount = std::size(kText);
380 constexpr int kLoopCount = 200;
383 for (int loop = 0; loop < kLoopCount; ++loop) {
384 for (size_t line = 0; line < kLineCount; ++line) {
385 y += font.getSpacing();
386 if (!canvas || y > 792 - 36) {
387 y = 36 + font.getSpacing();
388 canvas = doc->beginPage(612, 792);
389 background.notifyPixelsChanged();
390 canvas->drawBitmap(background, 0, 0);
391 }
392 canvas->drawString(kText[line], x, y, font, paint);
393 }
394 }
395}
396
397SkBitmap make_background() {
398 SkBitmap background;
400 bitmap.allocN32Pixels(32, 32);
401 bitmap.eraseColor(SK_ColorWHITE);
402 SkCanvas tmp(bitmap);
403 SkPaint gray;
404 gray.setColor(SkColorSetARGB(0xFF, 0xEE, 0xEE, 0xEE));
405 tmp.drawRect({0,0,16,16}, gray);
406 tmp.drawRect({16,16,32,32}, gray);
407 SkPaint shader;
408 shader.setShader(
409 SkShader::MakeBitmapShader(
410 bitmap, SkShader::kRepeat_TileMode, SkShader::kRepeat_TileMode));
411 background.allocN32Pixels(612, 792);
412 SkCanvas tmp2(background);
413 tmp2.drawPaint(shader);
414 return background;
415}
416
417struct PDFBigDocBench : public Benchmark {
418 bool fFast;
419 SkBitmap fBackground;
420 std::unique_ptr<SkExecutor> fExecutor;
421 PDFBigDocBench(bool fast) : fFast(fast) {}
422 void onDelayedSetup() override {
423 fBackground = make_background();
424 fExecutor = fFast ? SkExecutor::MakeFIFOThreadPool() : nullptr;
425 }
426 const char* onGetName() override {
427 static const char kNameFast[] = "PDFBigDocBench_fast";
428 static const char kNameSlow[] = "PDFBigDocBench_slow";
429 return fFast ? kNameFast : kNameSlow;
430 }
431 bool isSuitableFor(Backend backend) override { return backend == Backend::kNonRendering; }
432 void onDraw(int loops, SkCanvas*) override {
433 while (loops-- > 0) {
434 #ifdef SK_PDF_TEST_BIGDOCBENCH_OUTPUT
435 SkFILEWStream wStream("/tmp/big_pdf.pdf");
436 #else
437 SkNullWStream wStream;
438 #endif
439 SkPDF::Metadata metadata;
440 metadata.fExecutor = fExecutor.get();
441 auto doc = SkPDF::MakeDocument(&wStream, metadata);
442 big_pdf_test(doc.get(), fBackground);
443 }
444 }
445};
446} // namespace
447DEF_BENCH(return new PDFBigDocBench(false);)
448DEF_BENCH(return new PDFBigDocBench(true);)
449#endif
450
451#endif // SK_SUPPORT_PDF
SkPath fPath
#define DEF_BENCH(code)
Definition: Benchmark.h:20
const char * backend
const char * fName
float next_any(SkRandom *random)
Definition: PDFBench.cpp:70
float next_common(SkRandom *random)
Definition: PDFBench.cpp:67
std::unique_ptr< SkStreamAsset > GetResourceAsStream(const char *resource, bool useFileStream)
Definition: Resources.cpp:31
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SkASSERT(cond)
Definition: SkAssert.h:116
uint32_t SkColor
Definition: SkColor.h:37
constexpr SkColor SK_ColorBLUE
Definition: SkColor.h:135
constexpr SkColor SK_ColorRED
Definition: SkColor.h:126
static constexpr SkColor SkColorSetARGB(U8CPU a, U8CPU r, U8CPU g, U8CPU b)
Definition: SkColor.h:49
constexpr SkColor SK_ColorBLACK
Definition: SkColor.h:103
constexpr SkColor SK_ColorGREEN
Definition: SkColor.h:131
constexpr SkColor SK_ColorWHITE
Definition: SkColor.h:122
unsigned SkFloatToDecimal(float value, char output[kMaximumSkFloatToDecimalLength])
constexpr unsigned kMaximumSkFloatToDecimalLength
SkPDFIndirectReference SkPDFSerializeImage(const SkImage *img, SkPDFDocument *doc, int encodingQuality)
SkPDFIndirectReference SkPDFMakeShader(SkPDFDocument *doc, SkShader *shader, const SkMatrix &canvasTransform, const SkIRect &surfaceBBox, SkColor4f paintColor)
void SkPDFWriteByteString(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:248
void SkPDFWriteTextString(SkWStream *wStream, const char *cin, size_t len)
Definition: SkPDFTypes.cpp:245
SkPDFIndirectReference SkPDFStreamOut(std::unique_ptr< SkPDFDict > dict, std::unique_ptr< SkStreamAsset > content, SkPDFDocument *doc, SkPDFSteamCompressionEnabled compress)
Definition: SkPDFTypes.cpp:591
constexpr uint8_t SkToU8(S x)
Definition: SkTo.h:22
virtual void onDraw(int loops, SkCanvas *)=0
virtual bool isSuitableFor(Backend backend)
Definition: Benchmark.h:55
virtual void onDelayedSetup()
Definition: Benchmark.h:101
virtual const char * onGetName()=0
void alloc(const SkImageInfo &)
void notifyPixelsChanged() const
Definition: SkBitmap.cpp:365
void allocN32Pixels(int width, int height, bool isOpaque=false)
Definition: SkBitmap.cpp:232
void translate(SkScalar dx, SkScalar dy)
Definition: SkCanvas.cpp:1278
void clear(SkColor color)
Definition: SkCanvas.h:1199
void clipPath(const SkPath &path, SkClipOp op, bool doAntiAlias)
Definition: SkCanvas.cpp:1456
void drawString(const char str[], SkScalar x, SkScalar y, const SkFont &font, const SkPaint &paint)
Definition: SkCanvas.h:1803
SkCanvas * beginPage(SkScalar width, SkScalar height, const SkRect *content=nullptr)
Definition: SkDocument.cpp:32
static std::unique_ptr< SkExecutor > MakeFIFOThreadPool(int threads=0, bool allowBorrowing=true)
Definition: SkExecutor.cpp:146
Definition: SkFont.h:35
static sk_sp< SkShader > MakeLinear(const SkPoint pts[2], const SkColor colors[], const SkScalar pos[], int count, SkTileMode mode, uint32_t flags=0, const SkMatrix *localMatrix=nullptr)
static const SkMatrix & I()
Definition: SkMatrix.cpp:1544
void setColor(SkColor color)
Definition: SkPaint.cpp:119
@ kStroke_Style
set to stroke geometry
Definition: SkPaint.h:194
void setShader(sk_sp< SkShader > shader)
Definition: SkPath.h:59
SkPath & reset()
Definition: SkPath.cpp:370
SkPath & addRect(const SkRect &rect, SkPathDirection dir, unsigned start)
Definition: SkPath.cpp:864
uint32_t nextU()
Definition: SkRandom.h:42
float nextRangeF(float min, float max)
Definition: SkRandom.h:64
T * get() const
Definition: SkRefCnt.h:303
const Paint & paint
Definition: color_source.cc:38
DlColor color
static bool b
constexpr char kText[]
Definition: glyph_pos.cpp:28
double y
double x
constexpr SkColor4f kBlack
Definition: SkColor.h:435
SK_API sk_sp< SkImage > RasterFromPixmapCopy(const SkPixmap &pixmap)
size_t ColorToDecimal(uint8_t value, char result[5])
Definition: SkPDFUtils.cpp:307
SK_API sk_sp< SkDocument > MakeDocument(SkWStream *stream, const Metadata &metadata)
PODArray< SkColor > colors
Definition: SkRecords.h:276
sk_sp< SkImage > GetResourceAsImage(const char *resource)
Definition: DecodeUtils.h:25
SkFont DefaultFont()
Definition: bitmap.py:1
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
font
Font Metadata and Metrics.
dst
Definition: cp.py:12
PDFScalarBench(const char *n, float(*f)(SkRandom *))
Definition: PDFBench.cpp:50
const char * onGetName() override
Definition: PDFBench.cpp:56
void onDraw(int loops, SkCanvas *) override
Definition: PDFBench.cpp:57
const char * fName
Definition: PDFBench.cpp:51
bool isSuitableFor(Backend b) override
Definition: PDFBench.cpp:53
Definition: SkRect.h:32
static SkImageInfo MakeN32Premul(int width, int height)
SkExecutor * fExecutor
static SkRect Make(const SkISize &size)
Definition: SkRect.h:669