xref: /aosp_15_r20/external/pdfium/docs/safetynet.md (revision 3ac0a46f773bac49fa9476ec2b1cf3f8da5ec3a4)
1*3ac0a46fSAndroid Build Coastguard Worker# SafetyNet - Performance regression detection for PDFium
2*3ac0a46fSAndroid Build Coastguard Worker
3*3ac0a46fSAndroid Build Coastguard Worker[TOC]
4*3ac0a46fSAndroid Build Coastguard Worker
5*3ac0a46fSAndroid Build Coastguard WorkerThis document explains how to use SafetyNet to detect performance regressions
6*3ac0a46fSAndroid Build Coastguard Workerin PDFium.
7*3ac0a46fSAndroid Build Coastguard Worker
8*3ac0a46fSAndroid Build Coastguard Worker## Comparing performance of two versions of PDFium
9*3ac0a46fSAndroid Build Coastguard Worker
10*3ac0a46fSAndroid Build Coastguard Workersafetynet_compare.py is a script that compares the performance between two
11*3ac0a46fSAndroid Build Coastguard Workerversions of pdfium. This can be used to verify if a given change has caused
12*3ac0a46fSAndroid Build Coastguard Workeror will cause any positive or negative changes in performance for a set of test
13*3ac0a46fSAndroid Build Coastguard Workercases.
14*3ac0a46fSAndroid Build Coastguard Worker
15*3ac0a46fSAndroid Build Coastguard WorkerThe supported profilers are exclusive to Linux, so for now this can only be run
16*3ac0a46fSAndroid Build Coastguard Workeron Linux.
17*3ac0a46fSAndroid Build Coastguard Worker
18*3ac0a46fSAndroid Build Coastguard WorkerAn illustrative example is below, comparing the local code version to an older
19*3ac0a46fSAndroid Build Coastguard Workerversion. Positive % changes mean an increase in time/instructions to run the
20*3ac0a46fSAndroid Build Coastguard Workertest - a regression, while negative % changes mean a decrease in
21*3ac0a46fSAndroid Build Coastguard Workertime/instructions, therefore an improvement.
22*3ac0a46fSAndroid Build Coastguard Worker
23*3ac0a46fSAndroid Build Coastguard Worker```
24*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py ~/test_pdfs --branch-before beef5e4
25*3ac0a46fSAndroid Build Coastguard Worker================================================================================
26*3ac0a46fSAndroid Build Coastguard Worker   % Change      Time after  Test case
27*3ac0a46fSAndroid Build Coastguard Worker--------------------------------------------------------------------------------
28*3ac0a46fSAndroid Build Coastguard Worker   -0.1980%  45,703,820,326  ~/test_pdfs/PDF Reference 1-7.pdf
29*3ac0a46fSAndroid Build Coastguard Worker   -0.5678%      42,038,814  ~/test_pdfs/Page 24 - PDF Reference 1-7.pdf
30*3ac0a46fSAndroid Build Coastguard Worker   +0.2666%  10,983,158,809  ~/test_pdfs/Rival.pdf
31*3ac0a46fSAndroid Build Coastguard Worker   +0.0447%  10,413,890,748  ~/test_pdfs/dynamic.pdf
32*3ac0a46fSAndroid Build Coastguard Worker   -7.7228%      26,161,171  ~/test_pdfs/encrypted1234.pdf
33*3ac0a46fSAndroid Build Coastguard Worker   -0.2763%     102,084,398  ~/test_pdfs/ghost.pdf
34*3ac0a46fSAndroid Build Coastguard Worker   -3.7005%  10,800,642,262  ~/test_pdfs/musician.pdf
35*3ac0a46fSAndroid Build Coastguard Worker   -0.2266%  45,691,618,789  ~/test_pdfs/no_metadata.pdf
36*3ac0a46fSAndroid Build Coastguard Worker   +1.4440%  38,442,606,162  ~/test_pdfs/test7.pdf
37*3ac0a46fSAndroid Build Coastguard Worker   +0.0335%       9,286,083  ~/test_pdfs/testbulletpoint.pdf
38*3ac0a46fSAndroid Build Coastguard Worker================================================================================
39*3ac0a46fSAndroid Build Coastguard WorkerTest cases run: 10
40*3ac0a46fSAndroid Build Coastguard WorkerFailed to measure: 0
41*3ac0a46fSAndroid Build Coastguard WorkerRegressions: 0
42*3ac0a46fSAndroid Build Coastguard WorkerImprovements: 2
43*3ac0a46fSAndroid Build Coastguard Worker```
44*3ac0a46fSAndroid Build Coastguard Worker
45*3ac0a46fSAndroid Build Coastguard Worker### Usage
46*3ac0a46fSAndroid Build Coastguard Worker
47*3ac0a46fSAndroid Build Coastguard WorkerRun the safetynet_compare.py script in testing/tools to perform a comparison.
48*3ac0a46fSAndroid Build Coastguard WorkerPass one or more paths with test cases - each path can be either a .pdf file or
49*3ac0a46fSAndroid Build Coastguard Workera directory containing .pdf files. Other files in those directories are
50*3ac0a46fSAndroid Build Coastguard Workerignored.
51*3ac0a46fSAndroid Build Coastguard Worker
52*3ac0a46fSAndroid Build Coastguard WorkerThe following comparison modes are supported:
53*3ac0a46fSAndroid Build Coastguard Worker
54*3ac0a46fSAndroid Build Coastguard Worker1. Compare uncommitted changes against clean branch:
55*3ac0a46fSAndroid Build Coastguard Worker```shell
56*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs
57*3ac0a46fSAndroid Build Coastguard Worker```
58*3ac0a46fSAndroid Build Coastguard Worker
59*3ac0a46fSAndroid Build Coastguard Worker2. Compare current branch with another branch or commit:
60*3ac0a46fSAndroid Build Coastguard Worker```shell
61*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --branch-before another_branch
62*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --branch-before 1a3c5e7
63*3ac0a46fSAndroid Build Coastguard Worker```
64*3ac0a46fSAndroid Build Coastguard Worker
65*3ac0a46fSAndroid Build Coastguard Worker3. Compare two other branches or commits:
66*3ac0a46fSAndroid Build Coastguard Worker```shell
67*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after another_branch --branch-before yet_another_branch
68*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after 1a3c5e7 --branch-before 0b2d4f6
69*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --branch-after another_branch --branch-before 0b2d4f6
70*3ac0a46fSAndroid Build Coastguard Worker```
71*3ac0a46fSAndroid Build Coastguard Worker
72*3ac0a46fSAndroid Build Coastguard Worker4. Compare two build flag configurations:
73*3ac0a46fSAndroid Build Coastguard Worker```shell
74*3ac0a46fSAndroid Build Coastguard Worker$ gn args out/BuildConfig1
75*3ac0a46fSAndroid Build Coastguard Worker$ gn args out/BuildConfig2
76*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py path/to/pdfs --build-dir out/BuildConfig2 --build-dir-before out/BuildConfig1
77*3ac0a46fSAndroid Build Coastguard Worker```
78*3ac0a46fSAndroid Build Coastguard Worker
79*3ac0a46fSAndroid Build Coastguard Workersafetynet_compare.py takes care of checking out the appropriate branch, building
80*3ac0a46fSAndroid Build Coastguard Workerit, running the test cases and comparing results.
81*3ac0a46fSAndroid Build Coastguard Worker
82*3ac0a46fSAndroid Build Coastguard Worker### Profilers
83*3ac0a46fSAndroid Build Coastguard Worker
84*3ac0a46fSAndroid Build Coastguard Workersafetynet_compare.py uses callgrind as a profiler by default. Use --profiler
85*3ac0a46fSAndroid Build Coastguard Workerto specify another one. The supported ones are:
86*3ac0a46fSAndroid Build Coastguard Worker
87*3ac0a46fSAndroid Build Coastguard Worker#### perfstat
88*3ac0a46fSAndroid Build Coastguard Worker
89*3ac0a46fSAndroid Build Coastguard WorkerOnly works on Linux.
90*3ac0a46fSAndroid Build Coastguard WorkerMake sure you have perf by typing in the terminal:
91*3ac0a46fSAndroid Build Coastguard Worker```shell
92*3ac0a46fSAndroid Build Coastguard Worker$ perf
93*3ac0a46fSAndroid Build Coastguard Worker```
94*3ac0a46fSAndroid Build Coastguard Worker
95*3ac0a46fSAndroid Build Coastguard WorkerThis is a fast profiler, but uses sampling so it's slightly inaccurate.
96*3ac0a46fSAndroid Build Coastguard WorkerExpect variations of up to 1%, which is below the cutoff to consider a
97*3ac0a46fSAndroid Build Coastguard Workerchange significant.
98*3ac0a46fSAndroid Build Coastguard Worker
99*3ac0a46fSAndroid Build Coastguard WorkerUse this when running over large test sets to get good enough results.
100*3ac0a46fSAndroid Build Coastguard Worker
101*3ac0a46fSAndroid Build Coastguard Worker#### callgrind
102*3ac0a46fSAndroid Build Coastguard Worker
103*3ac0a46fSAndroid Build Coastguard WorkerOnly works on Linux.
104*3ac0a46fSAndroid Build Coastguard WorkerMake sure valgrind is installed:
105*3ac0a46fSAndroid Build Coastguard Worker```shell
106*3ac0a46fSAndroid Build Coastguard Worker$ valgrind
107*3ac0a46fSAndroid Build Coastguard Worker```
108*3ac0a46fSAndroid Build Coastguard Worker
109*3ac0a46fSAndroid Build Coastguard WorkerThis is a slow and accurate profiler. Expect variations of around 100
110*3ac0a46fSAndroid Build Coastguard Workerinstructions. However, this takes about 50 times longer to run than perf stat.
111*3ac0a46fSAndroid Build Coastguard Worker
112*3ac0a46fSAndroid Build Coastguard WorkerUse this when looking for small variations (< 1%).
113*3ac0a46fSAndroid Build Coastguard Worker
114*3ac0a46fSAndroid Build Coastguard WorkerOne advantage is that callgrind can generate `callgrind.out` files (by passing
115*3ac0a46fSAndroid Build Coastguard Worker--output-dir to safetynet_compare.py), which contain profiling information that
116*3ac0a46fSAndroid Build Coastguard Workercan be analyzed to find the cause of a regression. KCachegrind is a good
117*3ac0a46fSAndroid Build Coastguard Workervisualizer for these files.
118*3ac0a46fSAndroid Build Coastguard Worker
119*3ac0a46fSAndroid Build Coastguard Worker#### none
120*3ac0a46fSAndroid Build Coastguard Worker
121*3ac0a46fSAndroid Build Coastguard WorkerRun without any profiler, giving a performance score of 1 always. useful for
122*3ac0a46fSAndroid Build Coastguard Workerrunning image comparisons or debugging the script.
123*3ac0a46fSAndroid Build Coastguard Worker
124*3ac0a46fSAndroid Build Coastguard Worker### Common Options
125*3ac0a46fSAndroid Build Coastguard Worker
126*3ac0a46fSAndroid Build Coastguard WorkerArguments commonly passed to safetynet_compare.py.
127*3ac0a46fSAndroid Build Coastguard Worker
128*3ac0a46fSAndroid Build Coastguard Worker* --profiler: described above.
129*3ac0a46fSAndroid Build Coastguard Worker* --build-dir: this specified the build config with a relative path from the
130*3ac0a46fSAndroid Build Coastguard Workerpdfium src directory to the build directory. Defaults to out/Release.
131*3ac0a46fSAndroid Build Coastguard Worker* --output-dir: where to place the profiling output files. These are
132*3ac0a46fSAndroid Build Coastguard Workercallgrind.out.[test_case] files for callgrind, perfstat does not produce them.
133*3ac0a46fSAndroid Build Coastguard WorkerBy default they are not written.
134*3ac0a46fSAndroid Build Coastguard Worker* --case-order: sort test case results according to this metric. Can be "after",
135*3ac0a46fSAndroid Build Coastguard Worker"before", "ratio" and "rating". If not specified, sort by path.
136*3ac0a46fSAndroid Build Coastguard Worker* --this-repo: use the repository where the script is instead of checking out a
137*3ac0a46fSAndroid Build Coastguard Workertemporary one. This is faster and does not require downloads. Although it
138*3ac0a46fSAndroid Build Coastguard Workerrestores the state of the local repo, if the script is killed or crashes the
139*3ac0a46fSAndroid Build Coastguard Workeruncommitted changes can remain stashed and you may be on another branch.
140*3ac0a46fSAndroid Build Coastguard Worker
141*3ac0a46fSAndroid Build Coastguard Worker### Other Options
142*3ac0a46fSAndroid Build Coastguard Worker
143*3ac0a46fSAndroid Build Coastguard WorkerMost of the time these don't need to be used.
144*3ac0a46fSAndroid Build Coastguard Worker
145*3ac0a46fSAndroid Build Coastguard Worker* --build-dir-before: if comparing different build dirs (say, to test what a
146*3ac0a46fSAndroid Build Coastguard Workerflag flip does), specify the build dir for the “before” branch here and the
147*3ac0a46fSAndroid Build Coastguard Workerbuild dir for the “after” branch with --build-dir.
148*3ac0a46fSAndroid Build Coastguard Worker* --interesting-section: only the interesting section should be measured instead
149*3ac0a46fSAndroid Build Coastguard Workerof all the execution of the test harness. This only works in debug, since in
150*3ac0a46fSAndroid Build Coastguard Workerrelease the delimiters are stripped out. This does not work to compare branches
151*3ac0a46fSAndroid Build Coastguard Workerthat don’t have the callgrind delimiters, as it would otherwise be unfair to
152*3ac0a46fSAndroid Build Coastguard Workercompare a whole run vs the interesting section of another run.
153*3ac0a46fSAndroid Build Coastguard Worker* --machine-readable: output a json with the results that is easier to read by
154*3ac0a46fSAndroid Build Coastguard Workercode.
155*3ac0a46fSAndroid Build Coastguard Worker* --num-workers: how many workers to use to parallelize test case runs. Defaults
156*3ac0a46fSAndroid Build Coastguard Workerto # of CPUs in the machine.
157*3ac0a46fSAndroid Build Coastguard Worker* --threshold-significant: highlight differences that exceed this value.
158*3ac0a46fSAndroid Build Coastguard WorkerDefaults to 0.02.
159*3ac0a46fSAndroid Build Coastguard Worker* --tmp-dir: directory in which temporary repos will be cloned and downloads
160*3ac0a46fSAndroid Build Coastguard Workerwill be cached, if --this-repo is not enabled. Defaults to /tmp.
161*3ac0a46fSAndroid Build Coastguard Worker
162*3ac0a46fSAndroid Build Coastguard Worker## Setup a nightly job
163*3ac0a46fSAndroid Build Coastguard Worker
164*3ac0a46fSAndroid Build Coastguard WorkerCreate a separate checkout of pdfium in a new directory, for example `~/job`.
165*3ac0a46fSAndroid Build Coastguard WorkerThe safetynet_job.py script will run from this directory. This checkout needs to
166*3ac0a46fSAndroid Build Coastguard Workerbe `git pull`'ed when there are changes to the SafetyNet scripts, but otherwise
167*3ac0a46fSAndroid Build Coastguard Workerit can be left alone.
168*3ac0a46fSAndroid Build Coastguard Worker
169*3ac0a46fSAndroid Build Coastguard WorkerCreate a directory to contain the job results, for example `~/job_results`. In
170*3ac0a46fSAndroid Build Coastguard Workereach run, a `.log` file with the results will be written to this directory and a
171*3ac0a46fSAndroid Build Coastguard Workersubdirectory will be created with the other artifacts.
172*3ac0a46fSAndroid Build Coastguard Worker
173*3ac0a46fSAndroid Build Coastguard WorkerSetup a cron job to run safetynet_job.py nightly. The example below runs it at
174*3ac0a46fSAndroid Build Coastguard Worker1:42 AM, over the corpus in two directories: `~/pdf_samples/thousand_pdfs` and
175*3ac0a46fSAndroid Build Coastguard Worker`~/pdf_samples/i18n`
176*3ac0a46fSAndroid Build Coastguard Worker
177*3ac0a46fSAndroid Build Coastguard Worker```shell
178*3ac0a46fSAndroid Build Coastguard Worker@ crontab -e
179*3ac0a46fSAndroid Build Coastguard Worker42 1 * * * bash -lc '~/job/pdfium/testing/tools/safetynet_job.py ~/job_results ~/pdf_samples/thousand_pdfs ~/pdf_samples/i18n --output-to-log >> ~/job_results/cron_nightly.log 2>&1'
180*3ac0a46fSAndroid Build Coastguard Worker```
181*3ac0a46fSAndroid Build Coastguard Worker
182*3ac0a46fSAndroid Build Coastguard WorkerThe first time the job runs, it will just create a checkpoint as
183*3ac0a46fSAndroid Build Coastguard Worker`~/job_results/last_revision_covered`. From then on, since a checkpoint is
184*3ac0a46fSAndroid Build Coastguard Workeravailable, each run will compare performance with the last checkpoint and update
185*3ac0a46fSAndroid Build Coastguard Workerthe checkpoint.
186*3ac0a46fSAndroid Build Coastguard Worker
187*3ac0a46fSAndroid Build Coastguard Worker## Run image comparison
188*3ac0a46fSAndroid Build Coastguard Worker
189*3ac0a46fSAndroid Build Coastguard WorkerPass the `--png-dir` option pointing at an output directory to compare the output
190*3ac0a46fSAndroid Build Coastguard Workerimages from rendering the "before" and the "after" branches with pdfium_test.
191*3ac0a46fSAndroid Build Coastguard Worker
192*3ac0a46fSAndroid Build Coastguard Worker```shell
193*3ac0a46fSAndroid Build Coastguard Worker$ mkdir ~/output_images
194*3ac0a46fSAndroid Build Coastguard Worker$ testing/tools/safetynet_compare.py ~/pdf_samples --branch-before before_visual_changes --branch-after after_visual_changes --png-dir ~/output_images
195*3ac0a46fSAndroid Build Coastguard Worker```
196*3ac0a46fSAndroid Build Coastguard Worker
197*3ac0a46fSAndroid Build Coastguard WorkerThis will output and automatically open a `~/output_images/compare.html` file
198*3ac0a46fSAndroid Build Coastguard Workershowing the before/after and the diff. Hover the mouse cursor over the
199*3ac0a46fSAndroid Build Coastguard Workerbefore/after image on the left for an easier visual comparison. The "before"
200*3ac0a46fSAndroid Build Coastguard Workerimage is displayed until the cursor hovers over the image, which is then
201*3ac0a46fSAndroid Build Coastguard Workerreplaced with the "after" image.
202*3ac0a46fSAndroid Build Coastguard Worker
203*3ac0a46fSAndroid Build Coastguard WorkerIt is recommended to use `--profiler=none` with this option.
204