Add performance benchmark for shaping, get extents and draw
This commit is contained in:
parent
12a9d57292
commit
95b1081be4
@ -226,7 +226,9 @@ jobs:
|
||||
# test a meson based dist
|
||||
- run: meson dist -Cbuild && rm -rf build
|
||||
# test experimental APIs
|
||||
- run: meson build -Dexperimental_api=true && ninja -Cbuild test && rm -rf build
|
||||
- run: meson build -Dexperimental_api=true -Dbenchmark=true -Dexperimental_api=true -Doptimization=2 && ninja -Cbuild test # or meson test -Cbuild
|
||||
# run benchmarks
|
||||
- run: build/perf/perf && meson test -Cbuild --benchmark && rm -rf build # or ninja -Cbuild benchmark
|
||||
# mingw
|
||||
- run: .ci/build-win32.sh
|
||||
- store_artifacts:
|
||||
|
19
.github/workflows/linux-ci.yml
vendored
19
.github/workflows/linux-ci.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
- name: install meson and fonttools
|
||||
run: sudo pip3 install meson fonttools
|
||||
- name: run
|
||||
run: meson build -Db_coverage=true -Dglib=enabled -Dcairo=enabled -Dicu=enabled -Dgraphite=enabled -Dfreetype=enabled
|
||||
run: meson build -Db_coverage=true -Dglib=enabled -Dcairo=enabled -Dicu=enabled -Dgraphite=enabled -Dfreetype=enabled -Dbenchmark=true -Doptimization=2
|
||||
- name: ci
|
||||
run: meson test --print-errorlogs -Cbuild
|
||||
|
||||
@ -30,6 +30,23 @@ jobs:
|
||||
GH_TOKEN: ${{ secrets.GH_TOKEN }}
|
||||
REVISION: ${{ github.sha }}
|
||||
|
||||
# waiting for https://github.com/rhysd/github-action-benchmark/issues/36 to happen
|
||||
# - name: benchmark
|
||||
# run: build/perf/perf --benchmark_format=json > perf/result.json
|
||||
# - name: store benchmark result
|
||||
# uses: rhysd/github-action-benchmark@b2ee598
|
||||
# if: github.event_name != 'pull_request'
|
||||
# with:
|
||||
# name: C++ Benchmark
|
||||
# tool: 'googlecpp'
|
||||
# output-file-path: perf/result.json
|
||||
# gh-pages-branch: gh-pages
|
||||
# github-token: ${{ secrets.PERSONAL_GITHUB_TOKEN }}
|
||||
# auto-push: true
|
||||
# alert-threshold: '150%'
|
||||
# comment-on-alert: true
|
||||
# fail-on-alert: true
|
||||
|
||||
- name: cov
|
||||
run: ninja -Cbuild coverage
|
||||
- uses: codecov/codecov-action@v1
|
||||
|
@ -345,6 +345,10 @@ if not get_option('tests').disabled()
|
||||
subdir('test')
|
||||
endif
|
||||
|
||||
if get_option('benchmark')
|
||||
subdir('perf')
|
||||
endif
|
||||
|
||||
if not get_option('gtk_doc').disabled()
|
||||
subdir('docs')
|
||||
endif
|
||||
|
@ -28,6 +28,8 @@ option('introspection', type: 'feature', value: 'auto', yield: true,
|
||||
option('gtk_doc', type: 'feature', value: 'auto', yield: true,
|
||||
description: 'Generate documentation with gtk-doc')
|
||||
|
||||
option('benchmark', type : 'boolean', value : false,
|
||||
description: 'Enable benchmark tests')
|
||||
option('icu_builtin', type: 'boolean', value: false,
|
||||
description: 'Don\'t separate ICU support as harfbuzz-icu module')
|
||||
option('experimental_api', type: 'boolean', value: false,
|
||||
|
9
perf/meson.build
Normal file
9
perf/meson.build
Normal file
@ -0,0 +1,9 @@
|
||||
google_benchmark = subproject('google-benchmark')
|
||||
google_benchmark_dep = google_benchmark.get_variable('google_benchmark_dep')
|
||||
|
||||
benchmark('perf', executable('perf', 'perf.cc',
|
||||
dependencies : [google_benchmark_dep, freetype_dep],
|
||||
include_directories: [incconfig, incsrc],
|
||||
link_with: [libharfbuzz],
|
||||
install: false,
|
||||
), workdir: meson.current_source_dir() / '..', timeout: 100)
|
128
perf/perf-draw.hh
Normal file
128
perf/perf-draw.hh
Normal file
@ -0,0 +1,128 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ot.h"
|
||||
#include "hb-ft.h"
|
||||
#include FT_OUTLINE_H
|
||||
|
||||
#define HB_UNUSED __attribute__((unused))
|
||||
|
||||
static void
|
||||
_hb_move_to (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_hb_line_to (hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED, void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_hb_quadratic_to (hb_position_t control_x HB_UNUSED, hb_position_t control_y HB_UNUSED,
|
||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
||||
void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_hb_cubic_to (hb_position_t control1_x HB_UNUSED, hb_position_t control1_y HB_UNUSED,
|
||||
hb_position_t control2_x HB_UNUSED, hb_position_t control2_y HB_UNUSED,
|
||||
hb_position_t to_x HB_UNUSED, hb_position_t to_y HB_UNUSED,
|
||||
void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_hb_close_path (void *user_data HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_ft_move_to (const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_ft_line_to (const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_ft_conic_to (const FT_Vector* control HB_UNUSED, const FT_Vector* to HB_UNUSED,
|
||||
void* user HB_UNUSED) {}
|
||||
|
||||
static void
|
||||
_ft_cubic_to (const FT_Vector* control1 HB_UNUSED, const FT_Vector* control2 HB_UNUSED,
|
||||
const FT_Vector* to HB_UNUSED, void* user HB_UNUSED) {}
|
||||
|
||||
|
||||
static void draw (benchmark::State &state, const char *font_path, bool is_var, bool is_ft)
|
||||
{
|
||||
hb_font_t *font;
|
||||
unsigned num_glyphs;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
num_glyphs = hb_face_get_glyph_count (face);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
if (is_var)
|
||||
{
|
||||
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
|
||||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
if (is_ft)
|
||||
{
|
||||
FT_Face ft_face = hb_ft_font_get_face (font);
|
||||
hb_ft_font_set_load_flags (font, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
|
||||
|
||||
FT_Outline_Funcs draw_funcs;
|
||||
draw_funcs.move_to = (FT_Outline_MoveToFunc) _ft_move_to;
|
||||
draw_funcs.line_to = (FT_Outline_LineToFunc) _ft_line_to;
|
||||
draw_funcs.conic_to = (FT_Outline_ConicToFunc) _ft_conic_to;
|
||||
draw_funcs.cubic_to = (FT_Outline_CubicToFunc) _ft_cubic_to;
|
||||
draw_funcs.shift = 0;
|
||||
draw_funcs.delta = 0;
|
||||
|
||||
for (auto _ : state)
|
||||
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
||||
{
|
||||
FT_Load_Glyph (ft_face, gid, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
|
||||
FT_Outline_Decompose (&ft_face->glyph->outline, &draw_funcs, nullptr);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hb_draw_funcs_t *draw_funcs = hb_draw_funcs_create ();
|
||||
hb_draw_funcs_set_move_to_func (draw_funcs, _hb_move_to);
|
||||
hb_draw_funcs_set_line_to_func (draw_funcs, _hb_line_to);
|
||||
hb_draw_funcs_set_quadratic_to_func (draw_funcs, _hb_quadratic_to);
|
||||
hb_draw_funcs_set_cubic_to_func (draw_funcs, _hb_cubic_to);
|
||||
hb_draw_funcs_set_close_path_func (draw_funcs, _hb_close_path);
|
||||
|
||||
for (auto _ : state)
|
||||
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
||||
hb_font_draw_glyph (font, gid, draw_funcs, nullptr);
|
||||
|
||||
hb_draw_funcs_destroy (draw_funcs);
|
||||
}
|
||||
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
#define FONT_BASE_PATH "test/subset/data/fonts/"
|
||||
|
||||
BENCHMARK_CAPTURE (draw, cff - ot - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, false);
|
||||
BENCHMARK_CAPTURE (draw, cff - ft - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, cff2 - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, false);
|
||||
BENCHMARK_CAPTURE (draw, cff2 - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, cff2/vf - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, false);
|
||||
BENCHMARK_CAPTURE (draw, cff2/vf - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, glyf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (draw, glyf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, glyf/vf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, false);
|
||||
BENCHMARK_CAPTURE (draw, glyf/vf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, glyf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (draw, glyf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, glyf/vf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, false);
|
||||
BENCHMARK_CAPTURE (draw, glyf/vf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (draw, glyf - ot - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (draw, glyf - ft - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, true);
|
65
perf/perf-extents.hh
Normal file
65
perf/perf-extents.hh
Normal file
@ -0,0 +1,65 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "hb.h"
|
||||
#include "hb-ft.h"
|
||||
#include "hb-ot.h"
|
||||
|
||||
static void extents (benchmark::State &state, const char *font_path, bool is_var, bool is_ft)
|
||||
{
|
||||
hb_font_t *font;
|
||||
unsigned num_glyphs;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
num_glyphs = hb_face_get_glyph_count (face);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
if (is_var)
|
||||
{
|
||||
hb_variation_t wght = {HB_TAG ('w','g','h','t'), 500};
|
||||
hb_font_set_variations (font, &wght, 1);
|
||||
}
|
||||
|
||||
if (is_ft)
|
||||
{
|
||||
hb_ft_font_set_funcs (font);
|
||||
hb_ft_font_set_load_flags (font, FT_LOAD_NO_HINTING | FT_LOAD_NO_SCALE);
|
||||
}
|
||||
|
||||
hb_glyph_extents_t extents;
|
||||
for (auto _ : state)
|
||||
for (unsigned gid = 0; gid < num_glyphs; ++gid)
|
||||
hb_font_get_glyph_extents (font, gid, &extents);
|
||||
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
#define FONT_BASE_PATH "test/subset/data/fonts/"
|
||||
|
||||
BENCHMARK_CAPTURE (extents, cff - ot - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, false);
|
||||
BENCHMARK_CAPTURE (extents, cff - ft - SourceSansPro, FONT_BASE_PATH "SourceSansPro-Regular.otf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, cff2 - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, false);
|
||||
BENCHMARK_CAPTURE (extents, cff2 - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, cff2/vf - ot - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, false);
|
||||
BENCHMARK_CAPTURE (extents, cff2/vf - ft - AdobeVFPrototype, FONT_BASE_PATH "AdobeVFPrototype.otf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, glyf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (extents, glyf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, glyf/vf - ot - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, false);
|
||||
BENCHMARK_CAPTURE (extents, glyf/vf - ft - SourceSerifVariable, FONT_BASE_PATH "SourceSerifVariable-Roman.ttf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, glyf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (extents, glyf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", false, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, glyf/vf - ot - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, false);
|
||||
BENCHMARK_CAPTURE (extents, glyf/vf - ft - Comfortaa, FONT_BASE_PATH "Comfortaa-Regular-new.ttf", true, true);
|
||||
|
||||
BENCHMARK_CAPTURE (extents, glyf - ot - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, false);
|
||||
BENCHMARK_CAPTURE (extents, glyf - ft - Roboto, FONT_BASE_PATH "Roboto-Regular.ttf", false, true);
|
65
perf/perf-shaping.hh
Normal file
65
perf/perf-shaping.hh
Normal file
@ -0,0 +1,65 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#include "hb.h"
|
||||
|
||||
static void shape (benchmark::State &state, const char *text_path,
|
||||
hb_direction_t direction, hb_script_t script,
|
||||
const char *font_path)
|
||||
{
|
||||
hb_font_t *font;
|
||||
{
|
||||
hb_blob_t *blob = hb_blob_create_from_file (font_path);
|
||||
assert (hb_blob_get_length (blob));
|
||||
hb_face_t *face = hb_face_create (blob, 0);
|
||||
hb_blob_destroy (blob);
|
||||
font = hb_font_create (face);
|
||||
hb_face_destroy (face);
|
||||
}
|
||||
|
||||
hb_blob_t *text_blob = hb_blob_create_from_file (text_path);
|
||||
unsigned text_length;
|
||||
const char *text = hb_blob_get_data (text_blob, &text_length);
|
||||
assert (text_length);
|
||||
|
||||
hb_buffer_t *buf = hb_buffer_create ();
|
||||
for (auto _ : state)
|
||||
{
|
||||
hb_buffer_add_utf8 (buf, text, text_length, 0, -1);
|
||||
hb_buffer_set_direction (buf, direction);
|
||||
hb_buffer_set_script (buf, script);
|
||||
hb_shape (font, buf, nullptr, 0);
|
||||
hb_buffer_clear_contents (buf);
|
||||
}
|
||||
hb_buffer_destroy (buf);
|
||||
|
||||
hb_blob_destroy (text_blob);
|
||||
hb_font_destroy (font);
|
||||
}
|
||||
|
||||
BENCHMARK_CAPTURE (shape, fa-thelittleprince.txt - Amiri,
|
||||
"perf/texts/fa-thelittleprince.txt",
|
||||
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
|
||||
"perf/fonts/Amiri-Regular.ttf");
|
||||
BENCHMARK_CAPTURE (shape, fa-thelittleprince.txt - NotoNastaliqUrdu,
|
||||
"perf/texts/fa-thelittleprince.txt",
|
||||
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
|
||||
"perf/fonts/NotoNastaliqUrdu-Regular.ttf");
|
||||
|
||||
BENCHMARK_CAPTURE (shape, fa-monologue.txt - Amiri,
|
||||
"perf/texts/fa-monologue.txt",
|
||||
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
|
||||
"perf/fonts/Amiri-Regular.ttf");
|
||||
BENCHMARK_CAPTURE (shape, fa-monologue.txt - NotoNastaliqUrdu,
|
||||
"perf/texts/fa-monologue.txt",
|
||||
HB_DIRECTION_RTL, HB_SCRIPT_ARABIC,
|
||||
"perf/fonts/NotoNastaliqUrdu-Regular.ttf");
|
||||
|
||||
BENCHMARK_CAPTURE (shape, en-thelittleprince.txt - Roboto,
|
||||
"perf/texts/en-thelittleprince.txt",
|
||||
HB_DIRECTION_LTR, HB_SCRIPT_LATIN,
|
||||
"perf/fonts/Roboto-Regular.ttf");
|
||||
|
||||
BENCHMARK_CAPTURE (shape, en-words.txt - Roboto,
|
||||
"perf/texts/en-words.txt",
|
||||
HB_DIRECTION_LTR, HB_SCRIPT_LATIN,
|
||||
"perf/fonts/Roboto-Regular.ttf");
|
15
perf/perf.cc
Normal file
15
perf/perf.cc
Normal file
@ -0,0 +1,15 @@
|
||||
#include "benchmark/benchmark.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "perf-shaping.hh"
|
||||
#ifdef HAVE_FREETYPE
|
||||
#include "perf-extents.hh"
|
||||
#ifdef HB_EXPERIMENTAL_API
|
||||
#include "perf-draw.hh"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
BENCHMARK_MAIN ();
|
1
subprojects/.gitignore
vendored
1
subprojects/.gitignore
vendored
@ -6,3 +6,4 @@
|
||||
/proxy-libintl
|
||||
/zlib
|
||||
/packagecache
|
||||
/google-benchmark
|
||||
|
8
subprojects/google-benchmark.wrap
Normal file
8
subprojects/google-benchmark.wrap
Normal file
@ -0,0 +1,8 @@
|
||||
[wrap-file]
|
||||
directory = benchmark-1.4.1
|
||||
source_url = https://github.com/google/benchmark/archive/v1.4.1.zip
|
||||
source_filename = benchmark-1.4.1.zip
|
||||
source_hash = 61ae07eb5d4a0b02753419eb17a82b7d322786bb36ab62bd3df331a4d47c00a7
|
||||
patch_url = https://wrapdb.mesonbuild.com/v1/projects/google-benchmark/1.4.1/1/get_zip
|
||||
patch_filename = google-benchmark-1.4.1-1-wrap.zip
|
||||
patch_hash = 4cc5fe02ebd4fc82e110919b7977d7463eb2a99e4ecb9feca920eab6fd911d67
|
Loading…
Reference in New Issue
Block a user