xref: /aosp_15_r20/external/harfbuzz_ng/perf/benchmark-subset.cc (revision 2d1272b857b1f7575e6e246373e1cb218663db8a)
1*2d1272b8SAndroid Build Coastguard Worker #include "hb-benchmark.hh"
2*2d1272b8SAndroid Build Coastguard Worker 
3*2d1272b8SAndroid Build Coastguard Worker enum operation_t
4*2d1272b8SAndroid Build Coastguard Worker {
5*2d1272b8SAndroid Build Coastguard Worker   subset_glyphs,
6*2d1272b8SAndroid Build Coastguard Worker   subset_unicodes,
7*2d1272b8SAndroid Build Coastguard Worker   instance,
8*2d1272b8SAndroid Build Coastguard Worker };
9*2d1272b8SAndroid Build Coastguard Worker 
10*2d1272b8SAndroid Build Coastguard Worker struct axis_location_t
11*2d1272b8SAndroid Build Coastguard Worker {
12*2d1272b8SAndroid Build Coastguard Worker   hb_tag_t axis_tag;
13*2d1272b8SAndroid Build Coastguard Worker   float axis_value;
14*2d1272b8SAndroid Build Coastguard Worker };
15*2d1272b8SAndroid Build Coastguard Worker 
16*2d1272b8SAndroid Build Coastguard Worker static const axis_location_t
17*2d1272b8SAndroid Build Coastguard Worker _roboto_flex_instance_opts[] =
18*2d1272b8SAndroid Build Coastguard Worker {
19*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('w', 'g', 'h', 't'), 600.f},
20*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('w', 'd', 't', 'h'), 75.f},
21*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('o', 'p', 's', 'z'), 90.f},
22*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('G', 'R', 'A', 'D'), -100.f},
23*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('s', 'l', 'n', 't'), -3.f},
24*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('X', 'T', 'R', 'A'), 500.f},
25*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('X', 'O', 'P', 'Q'), 150.f},
26*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'O', 'P', 'Q'), 100.f},
27*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'T', 'L', 'C'), 480.f},
28*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'T', 'U', 'C'), 600.f},
29*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'T', 'A', 'S'), 800.f},
30*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'T', 'D', 'E'), -50.f},
31*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('Y', 'T', 'F', 'I'), 600.f},
32*2d1272b8SAndroid Build Coastguard Worker };
33*2d1272b8SAndroid Build Coastguard Worker 
34*2d1272b8SAndroid Build Coastguard Worker static const axis_location_t
35*2d1272b8SAndroid Build Coastguard Worker _mplus_instance_opts[] =
36*2d1272b8SAndroid Build Coastguard Worker {
37*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('w', 'g', 'h', 't'), 800.f},
38*2d1272b8SAndroid Build Coastguard Worker };
39*2d1272b8SAndroid Build Coastguard Worker 
40*2d1272b8SAndroid Build Coastguard Worker static const axis_location_t
41*2d1272b8SAndroid Build Coastguard Worker _fraunces_partial_instance_opts[] =
42*2d1272b8SAndroid Build Coastguard Worker {
43*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('S', 'O', 'F', 'T'), 75.0f},
44*2d1272b8SAndroid Build Coastguard Worker   {HB_TAG ('W', 'O', 'N', 'K'), 0.75f},
45*2d1272b8SAndroid Build Coastguard Worker };
46*2d1272b8SAndroid Build Coastguard Worker 
47*2d1272b8SAndroid Build Coastguard Worker template <typename Type, unsigned int n>
ARRAY_LEN(const Type (&)[n])48*2d1272b8SAndroid Build Coastguard Worker static inline unsigned int ARRAY_LEN (const Type (&)[n]) { return n; }
49*2d1272b8SAndroid Build Coastguard Worker 
50*2d1272b8SAndroid Build Coastguard Worker #define SUBSET_FONT_BASE_PATH "test/subset/data/fonts/"
51*2d1272b8SAndroid Build Coastguard Worker 
52*2d1272b8SAndroid Build Coastguard Worker struct test_input_t
53*2d1272b8SAndroid Build Coastguard Worker {
54*2d1272b8SAndroid Build Coastguard Worker   const char *font_path;
55*2d1272b8SAndroid Build Coastguard Worker   unsigned max_subset_size;
56*2d1272b8SAndroid Build Coastguard Worker   const axis_location_t *instance_opts;
57*2d1272b8SAndroid Build Coastguard Worker   unsigned num_instance_opts;
58*2d1272b8SAndroid Build Coastguard Worker } default_tests[] =
59*2d1272b8SAndroid Build Coastguard Worker {
60*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "Roboto-Regular.ttf", 1000, nullptr, 0},
61*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "Amiri-Regular.ttf", 4096, nullptr, 0},
62*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "NotoNastaliqUrdu-Regular.ttf", 1400, nullptr, 0},
63*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "NotoSansDevanagari-Regular.ttf", 1000, nullptr, 0},
64*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "Mplus1p-Regular.ttf", 10000, nullptr, 0},
65*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "SourceHanSans-Regular_subset.otf", 10000, nullptr, 0},
66*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "SourceSansPro-Regular.otf", 2000, nullptr, 0},
67*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "AdobeVFPrototype.otf", 300, nullptr, 0},
68*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "MPLUS1-Variable.ttf", 6000, _mplus_instance_opts, ARRAY_LEN (_mplus_instance_opts)},
69*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "RobotoFlex-Variable.ttf", 900, _roboto_flex_instance_opts, ARRAY_LEN (_roboto_flex_instance_opts)},
70*2d1272b8SAndroid Build Coastguard Worker   {SUBSET_FONT_BASE_PATH "Fraunces.ttf", 900, _fraunces_partial_instance_opts, ARRAY_LEN (_fraunces_partial_instance_opts)},
71*2d1272b8SAndroid Build Coastguard Worker #if 0
72*2d1272b8SAndroid Build Coastguard Worker   {"perf/fonts/NotoSansCJKsc-VF.ttf", 100000},
73*2d1272b8SAndroid Build Coastguard Worker #endif
74*2d1272b8SAndroid Build Coastguard Worker };
75*2d1272b8SAndroid Build Coastguard Worker 
76*2d1272b8SAndroid Build Coastguard Worker static test_input_t *tests = default_tests;
77*2d1272b8SAndroid Build Coastguard Worker static unsigned num_tests = sizeof (default_tests) / sizeof (default_tests[0]);
78*2d1272b8SAndroid Build Coastguard Worker 
79*2d1272b8SAndroid Build Coastguard Worker 
AddCodepoints(const hb_set_t * codepoints_in_font,unsigned subset_size,hb_subset_input_t * input)80*2d1272b8SAndroid Build Coastguard Worker void AddCodepoints(const hb_set_t* codepoints_in_font,
81*2d1272b8SAndroid Build Coastguard Worker                    unsigned subset_size,
82*2d1272b8SAndroid Build Coastguard Worker                    hb_subset_input_t* input)
83*2d1272b8SAndroid Build Coastguard Worker {
84*2d1272b8SAndroid Build Coastguard Worker   auto *unicodes = hb_subset_input_unicode_set (input);
85*2d1272b8SAndroid Build Coastguard Worker   hb_codepoint_t cp = HB_SET_VALUE_INVALID;
86*2d1272b8SAndroid Build Coastguard Worker   for (unsigned i = 0; i < subset_size; i++) {
87*2d1272b8SAndroid Build Coastguard Worker     // TODO(garretrieger): pick randomly.
88*2d1272b8SAndroid Build Coastguard Worker     if (!hb_set_next (codepoints_in_font, &cp)) return;
89*2d1272b8SAndroid Build Coastguard Worker     hb_set_add (unicodes, cp);
90*2d1272b8SAndroid Build Coastguard Worker   }
91*2d1272b8SAndroid Build Coastguard Worker }
92*2d1272b8SAndroid Build Coastguard Worker 
AddGlyphs(unsigned num_glyphs_in_font,unsigned subset_size,hb_subset_input_t * input)93*2d1272b8SAndroid Build Coastguard Worker void AddGlyphs(unsigned num_glyphs_in_font,
94*2d1272b8SAndroid Build Coastguard Worker                unsigned subset_size,
95*2d1272b8SAndroid Build Coastguard Worker                hb_subset_input_t* input)
96*2d1272b8SAndroid Build Coastguard Worker {
97*2d1272b8SAndroid Build Coastguard Worker   auto *glyphs = hb_subset_input_glyph_set (input);
98*2d1272b8SAndroid Build Coastguard Worker   for (unsigned i = 0; i < subset_size && i < num_glyphs_in_font; i++) {
99*2d1272b8SAndroid Build Coastguard Worker     if (i + 1 == subset_size &&
100*2d1272b8SAndroid Build Coastguard Worker         hb_subset_input_get_flags (input) & HB_SUBSET_FLAGS_RETAIN_GIDS)
101*2d1272b8SAndroid Build Coastguard Worker     {
102*2d1272b8SAndroid Build Coastguard Worker       hb_set_add (glyphs, num_glyphs_in_font - 1);
103*2d1272b8SAndroid Build Coastguard Worker       continue;
104*2d1272b8SAndroid Build Coastguard Worker     }
105*2d1272b8SAndroid Build Coastguard Worker     hb_set_add (glyphs, i);
106*2d1272b8SAndroid Build Coastguard Worker   }
107*2d1272b8SAndroid Build Coastguard Worker }
108*2d1272b8SAndroid Build Coastguard Worker 
109*2d1272b8SAndroid Build Coastguard Worker // Preprocess face and populate the subset accelerator on it to speed up
110*2d1272b8SAndroid Build Coastguard Worker // the subsetting operations.
preprocess_face(hb_face_t * face)111*2d1272b8SAndroid Build Coastguard Worker static hb_face_t* preprocess_face(hb_face_t* face)
112*2d1272b8SAndroid Build Coastguard Worker {
113*2d1272b8SAndroid Build Coastguard Worker   hb_face_t* new_face = hb_subset_preprocess(face);
114*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy(face);
115*2d1272b8SAndroid Build Coastguard Worker   return new_face;
116*2d1272b8SAndroid Build Coastguard Worker }
117*2d1272b8SAndroid Build Coastguard Worker 
118*2d1272b8SAndroid Build Coastguard Worker static hb_face_t *cached_face;
119*2d1272b8SAndroid Build Coastguard Worker 
120*2d1272b8SAndroid Build Coastguard Worker static void
free_cached_face(void)121*2d1272b8SAndroid Build Coastguard Worker free_cached_face (void)
122*2d1272b8SAndroid Build Coastguard Worker {
123*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (cached_face);
124*2d1272b8SAndroid Build Coastguard Worker   cached_face = nullptr;
125*2d1272b8SAndroid Build Coastguard Worker }
126*2d1272b8SAndroid Build Coastguard Worker 
127*2d1272b8SAndroid Build Coastguard Worker 
128*2d1272b8SAndroid Build Coastguard Worker /* benchmark for subsetting a font */
BM_subset(benchmark::State & state,operation_t operation,const test_input_t & test_input,bool retain_gids)129*2d1272b8SAndroid Build Coastguard Worker static void BM_subset (benchmark::State &state,
130*2d1272b8SAndroid Build Coastguard Worker                        operation_t operation,
131*2d1272b8SAndroid Build Coastguard Worker                        const test_input_t &test_input,
132*2d1272b8SAndroid Build Coastguard Worker                        bool retain_gids)
133*2d1272b8SAndroid Build Coastguard Worker {
134*2d1272b8SAndroid Build Coastguard Worker   unsigned subset_size = state.range(0);
135*2d1272b8SAndroid Build Coastguard Worker 
136*2d1272b8SAndroid Build Coastguard Worker   hb_face_t *face = nullptr;
137*2d1272b8SAndroid Build Coastguard Worker 
138*2d1272b8SAndroid Build Coastguard Worker   static const char *cached_font_path;
139*2d1272b8SAndroid Build Coastguard Worker 
140*2d1272b8SAndroid Build Coastguard Worker   if (!cached_font_path || strcmp (cached_font_path, test_input.font_path))
141*2d1272b8SAndroid Build Coastguard Worker   {
142*2d1272b8SAndroid Build Coastguard Worker     face = hb_benchmark_face_create_from_file_or_fail (test_input.font_path, 0);
143*2d1272b8SAndroid Build Coastguard Worker     assert (face);
144*2d1272b8SAndroid Build Coastguard Worker 
145*2d1272b8SAndroid Build Coastguard Worker     face = preprocess_face (face);
146*2d1272b8SAndroid Build Coastguard Worker 
147*2d1272b8SAndroid Build Coastguard Worker     if (cached_face)
148*2d1272b8SAndroid Build Coastguard Worker       hb_face_destroy (cached_face);
149*2d1272b8SAndroid Build Coastguard Worker 
150*2d1272b8SAndroid Build Coastguard Worker     cached_face = hb_face_reference (face);
151*2d1272b8SAndroid Build Coastguard Worker     cached_font_path = test_input.font_path;
152*2d1272b8SAndroid Build Coastguard Worker   }
153*2d1272b8SAndroid Build Coastguard Worker   else
154*2d1272b8SAndroid Build Coastguard Worker     face = hb_face_reference (cached_face);
155*2d1272b8SAndroid Build Coastguard Worker 
156*2d1272b8SAndroid Build Coastguard Worker   hb_subset_input_t* input = hb_subset_input_create_or_fail ();
157*2d1272b8SAndroid Build Coastguard Worker   assert (input);
158*2d1272b8SAndroid Build Coastguard Worker 
159*2d1272b8SAndroid Build Coastguard Worker   if (retain_gids)
160*2d1272b8SAndroid Build Coastguard Worker     hb_subset_input_set_flags (input, HB_SUBSET_FLAGS_RETAIN_GIDS);
161*2d1272b8SAndroid Build Coastguard Worker 
162*2d1272b8SAndroid Build Coastguard Worker   switch (operation)
163*2d1272b8SAndroid Build Coastguard Worker   {
164*2d1272b8SAndroid Build Coastguard Worker     case subset_unicodes:
165*2d1272b8SAndroid Build Coastguard Worker     {
166*2d1272b8SAndroid Build Coastguard Worker       hb_set_t* all_codepoints = hb_set_create ();
167*2d1272b8SAndroid Build Coastguard Worker       hb_face_collect_unicodes (face, all_codepoints);
168*2d1272b8SAndroid Build Coastguard Worker       AddCodepoints(all_codepoints, subset_size, input);
169*2d1272b8SAndroid Build Coastguard Worker       hb_set_destroy (all_codepoints);
170*2d1272b8SAndroid Build Coastguard Worker     }
171*2d1272b8SAndroid Build Coastguard Worker     break;
172*2d1272b8SAndroid Build Coastguard Worker 
173*2d1272b8SAndroid Build Coastguard Worker     case subset_glyphs:
174*2d1272b8SAndroid Build Coastguard Worker     {
175*2d1272b8SAndroid Build Coastguard Worker       unsigned num_glyphs = hb_face_get_glyph_count (face);
176*2d1272b8SAndroid Build Coastguard Worker       AddGlyphs(num_glyphs, subset_size, input);
177*2d1272b8SAndroid Build Coastguard Worker     }
178*2d1272b8SAndroid Build Coastguard Worker     break;
179*2d1272b8SAndroid Build Coastguard Worker 
180*2d1272b8SAndroid Build Coastguard Worker     case instance:
181*2d1272b8SAndroid Build Coastguard Worker     {
182*2d1272b8SAndroid Build Coastguard Worker       hb_set_t* all_codepoints = hb_set_create ();
183*2d1272b8SAndroid Build Coastguard Worker       hb_face_collect_unicodes (face, all_codepoints);
184*2d1272b8SAndroid Build Coastguard Worker       AddCodepoints(all_codepoints, subset_size, input);
185*2d1272b8SAndroid Build Coastguard Worker       hb_set_destroy (all_codepoints);
186*2d1272b8SAndroid Build Coastguard Worker 
187*2d1272b8SAndroid Build Coastguard Worker       hb_subset_input_set_flags(input, hb_subset_input_get_flags(input) | HB_SUBSET_FLAGS_OPTIMIZE_IUP_DELTAS);
188*2d1272b8SAndroid Build Coastguard Worker 
189*2d1272b8SAndroid Build Coastguard Worker       for (unsigned i = 0; i < test_input.num_instance_opts; i++)
190*2d1272b8SAndroid Build Coastguard Worker         hb_subset_input_pin_axis_location (input, face,
191*2d1272b8SAndroid Build Coastguard Worker                                            test_input.instance_opts[i].axis_tag,
192*2d1272b8SAndroid Build Coastguard Worker                                            test_input.instance_opts[i].axis_value);
193*2d1272b8SAndroid Build Coastguard Worker     }
194*2d1272b8SAndroid Build Coastguard Worker     break;
195*2d1272b8SAndroid Build Coastguard Worker   }
196*2d1272b8SAndroid Build Coastguard Worker 
197*2d1272b8SAndroid Build Coastguard Worker   for (auto _ : state)
198*2d1272b8SAndroid Build Coastguard Worker   {
199*2d1272b8SAndroid Build Coastguard Worker     hb_face_t* subset = hb_subset_or_fail (face, input);
200*2d1272b8SAndroid Build Coastguard Worker     assert (subset);
201*2d1272b8SAndroid Build Coastguard Worker     hb_face_destroy (subset);
202*2d1272b8SAndroid Build Coastguard Worker   }
203*2d1272b8SAndroid Build Coastguard Worker 
204*2d1272b8SAndroid Build Coastguard Worker   hb_subset_input_destroy (input);
205*2d1272b8SAndroid Build Coastguard Worker   hb_face_destroy (face);
206*2d1272b8SAndroid Build Coastguard Worker }
207*2d1272b8SAndroid Build Coastguard Worker 
test_subset(operation_t op,const char * op_name,bool retain_gids,benchmark::TimeUnit time_unit,const test_input_t & test_input)208*2d1272b8SAndroid Build Coastguard Worker static void test_subset (operation_t op,
209*2d1272b8SAndroid Build Coastguard Worker                          const char *op_name,
210*2d1272b8SAndroid Build Coastguard Worker                          bool retain_gids,
211*2d1272b8SAndroid Build Coastguard Worker                          benchmark::TimeUnit time_unit,
212*2d1272b8SAndroid Build Coastguard Worker                          const test_input_t &test_input)
213*2d1272b8SAndroid Build Coastguard Worker {
214*2d1272b8SAndroid Build Coastguard Worker   if (op == instance && test_input.instance_opts == nullptr)
215*2d1272b8SAndroid Build Coastguard Worker     return;
216*2d1272b8SAndroid Build Coastguard Worker 
217*2d1272b8SAndroid Build Coastguard Worker   char name[1024] = "BM_subset/";
218*2d1272b8SAndroid Build Coastguard Worker   strcat (name, op_name);
219*2d1272b8SAndroid Build Coastguard Worker   strcat (name, "/");
220*2d1272b8SAndroid Build Coastguard Worker   const char *p = strrchr (test_input.font_path, '/');
221*2d1272b8SAndroid Build Coastguard Worker   strcat (name, p ? p + 1 : test_input.font_path);
222*2d1272b8SAndroid Build Coastguard Worker   if (retain_gids)
223*2d1272b8SAndroid Build Coastguard Worker     strcat (name, "/retaingids");
224*2d1272b8SAndroid Build Coastguard Worker 
225*2d1272b8SAndroid Build Coastguard Worker   benchmark::RegisterBenchmark (name, BM_subset, op, test_input, retain_gids)
226*2d1272b8SAndroid Build Coastguard Worker       ->Range(10, test_input.max_subset_size)
227*2d1272b8SAndroid Build Coastguard Worker       ->Unit(time_unit);
228*2d1272b8SAndroid Build Coastguard Worker }
229*2d1272b8SAndroid Build Coastguard Worker 
test_operation(operation_t op,const char * op_name,const test_input_t * tests,unsigned num_tests,benchmark::TimeUnit time_unit)230*2d1272b8SAndroid Build Coastguard Worker static void test_operation (operation_t op,
231*2d1272b8SAndroid Build Coastguard Worker                             const char *op_name,
232*2d1272b8SAndroid Build Coastguard Worker                             const test_input_t *tests,
233*2d1272b8SAndroid Build Coastguard Worker                             unsigned num_tests,
234*2d1272b8SAndroid Build Coastguard Worker                             benchmark::TimeUnit time_unit)
235*2d1272b8SAndroid Build Coastguard Worker {
236*2d1272b8SAndroid Build Coastguard Worker   for (unsigned i = 0; i < num_tests; i++)
237*2d1272b8SAndroid Build Coastguard Worker   {
238*2d1272b8SAndroid Build Coastguard Worker     auto& test_input = tests[i];
239*2d1272b8SAndroid Build Coastguard Worker     test_subset (op, op_name, true, time_unit, test_input);
240*2d1272b8SAndroid Build Coastguard Worker     test_subset (op, op_name, false, time_unit, test_input);
241*2d1272b8SAndroid Build Coastguard Worker   }
242*2d1272b8SAndroid Build Coastguard Worker }
243*2d1272b8SAndroid Build Coastguard Worker 
main(int argc,char ** argv)244*2d1272b8SAndroid Build Coastguard Worker int main(int argc, char** argv)
245*2d1272b8SAndroid Build Coastguard Worker {
246*2d1272b8SAndroid Build Coastguard Worker   benchmark::Initialize(&argc, argv);
247*2d1272b8SAndroid Build Coastguard Worker 
248*2d1272b8SAndroid Build Coastguard Worker #ifndef HB_NO_ATEXIT
249*2d1272b8SAndroid Build Coastguard Worker   atexit (free_cached_face);
250*2d1272b8SAndroid Build Coastguard Worker #endif
251*2d1272b8SAndroid Build Coastguard Worker 
252*2d1272b8SAndroid Build Coastguard Worker   if (argc > 1)
253*2d1272b8SAndroid Build Coastguard Worker   {
254*2d1272b8SAndroid Build Coastguard Worker     num_tests = (argc - 1) / 2;
255*2d1272b8SAndroid Build Coastguard Worker     tests = (test_input_t *) calloc (num_tests, sizeof (test_input_t));
256*2d1272b8SAndroid Build Coastguard Worker     for (unsigned i = 0; i < num_tests; i++)
257*2d1272b8SAndroid Build Coastguard Worker     {
258*2d1272b8SAndroid Build Coastguard Worker       tests[i].font_path = argv[1 + i * 2];
259*2d1272b8SAndroid Build Coastguard Worker       tests[i].max_subset_size = atoi (argv[2 + i * 2]);
260*2d1272b8SAndroid Build Coastguard Worker     }
261*2d1272b8SAndroid Build Coastguard Worker   }
262*2d1272b8SAndroid Build Coastguard Worker 
263*2d1272b8SAndroid Build Coastguard Worker #define TEST_OPERATION(op, time_unit) test_operation (op, #op, tests, num_tests, time_unit)
264*2d1272b8SAndroid Build Coastguard Worker 
265*2d1272b8SAndroid Build Coastguard Worker   TEST_OPERATION (subset_glyphs, benchmark::kMicrosecond);
266*2d1272b8SAndroid Build Coastguard Worker   TEST_OPERATION (subset_unicodes, benchmark::kMicrosecond);
267*2d1272b8SAndroid Build Coastguard Worker   TEST_OPERATION (instance, benchmark::kMicrosecond);
268*2d1272b8SAndroid Build Coastguard Worker 
269*2d1272b8SAndroid Build Coastguard Worker #undef TEST_OPERATION
270*2d1272b8SAndroid Build Coastguard Worker 
271*2d1272b8SAndroid Build Coastguard Worker   benchmark::RunSpecifiedBenchmarks();
272*2d1272b8SAndroid Build Coastguard Worker   benchmark::Shutdown();
273*2d1272b8SAndroid Build Coastguard Worker 
274*2d1272b8SAndroid Build Coastguard Worker   if (tests != default_tests)
275*2d1272b8SAndroid Build Coastguard Worker     free (tests);
276*2d1272b8SAndroid Build Coastguard Worker }
277