Merge branch 'pgo-clang-11'

Closes #418
This commit is contained in:
Daniel Eklöf 2021-03-28 13:20:11 +02:00
commit a8c5168516
No known key found for this signature in database
GPG key ID: 5BBD4992C116573F
7 changed files with 118 additions and 54 deletions

View file

@ -27,6 +27,11 @@
## Unreleased ## Unreleased
### Added ### Added
### Changed ### Changed
* Update PGO build instructions in `INSTALL.md`
(https://codeberg.org/dnkl/foot/issues/418).
### Deprecated ### Deprecated
### Removed ### Removed
### Fixed ### Fixed

View file

@ -65,6 +65,7 @@ In addition to the dev variant of the packages above, you need:
* wayland protocols * wayland protocols
* ncurses (needed to generate terminfo) * ncurses (needed to generate terminfo)
* scdoc (for man page generation) * scdoc (for man page generation)
* llvm (for PGO builds with Clang)
* [tllist](https://codeberg.org/dnkl/tllist) [^1] * [tllist](https://codeberg.org/dnkl/tllist) [^1]
A note on compilers; in general, foot runs **much** faster when A note on compilers; in general, foot runs **much** faster when
@ -184,21 +185,15 @@ slower!) binary.
First, configure the build directory: First, configure the build directory:
```sh ```sh
export CFLAGS="$CFLAGS -O3 -Wno-missing-profile" export CFLAGS="$CFLAGS -O3"
meson --buildtype=release --prefix=/usr -Db_lto=true ../.. meson --buildtype=release --prefix=/usr -Db_lto=true ../..
``` ```
It is **very** important `-O3` is being used here, as GCC-10.1.x and It is **very** important `-O3` is being used here, as GCC-10.1.x and
later have a regression where PGO with `-O2` is **much** slower. later have a regression where PGO with `-O2` is **much** slower.
If you are using Clang instead of GCC, use the following `CFLAGS` instead: Clang users **must** add `-Wno-ignored-optimization-argument` to
`CFLAGS`.
```sh
export CFLAGS="$CFLAGS -O3 \
-Wno-ignored-optimization-argument \
-Wno-profile-instr-out-of-date \
-Wno-profile-instr-unprofiled"
```
Then, tell meson we want to _generate_ profiling data, and build: Then, tell meson we want to _generate_ profiling data, and build:
@ -234,6 +229,8 @@ We will use the `pgo` binary along with input corpus generated by
`scripts/generate-alt-random-writes.py`: `scripts/generate-alt-random-writes.py`:
```sh ```sh
./footclient --version
./foot --version
tmp_file=$(mktemp) tmp_file=$(mktemp)
../../scripts/generate-alt-random-writes \ ../../scripts/generate-alt-random-writes \
--rows=67 \ --rows=67 \
@ -253,7 +250,12 @@ tmp_file=$(mktemp)
rm ${tmp_file} rm ${tmp_file}
``` ```
The snippet above first creates an (empty) temporary file. Then, it The first step, running `./foot --version` and `./footclient
--version` might seem unnecessary, but is needed to ensure we have
_some_ profiling data for functions not covered by the PGO helper
binary. Without this, the final link phase will fail.
The snippet above then creates an (empty) temporary file. Then, it
runs a script that generates random escape sequences (if you cat runs a script that generates random escape sequences (if you cat
`${tmp_file}` in a terminal, youll see random colored characters all `${tmp_file}` in a terminal, youll see random colored characters all
over the screen). Finally, we feed the randomly generated escape over the screen). Finally, we feed the randomly generated escape
@ -271,14 +273,19 @@ This method requires a running Wayland session.
We will use the script `scripts/generate-alt-random-writes.py`: We will use the script `scripts/generate-alt-random-writes.py`:
```sh ```sh
./footclient --version
foot_tmp_file=$(mktemp) foot_tmp_file=$(mktemp)
./foot --config=/dev/null --term=xterm sh -c "<path-to-generate-alt-random-writes.py> --scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline ${foot_tmp_file} && cat ${foot_tmp_file}" ./foot --config=/dev/null --term=xterm sh -c "<path-to-generate-alt-random-writes.py> --scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel ${foot_tmp_file} && cat ${foot_tmp_file}"
rm ${foot_tmp_file} rm ${foot_tmp_file}
``` ```
You should see a foot window open up, with random colored text. The You should see a foot window open up, with random colored text. The
window should close after ~1-2s. window should close after ~1-2s.
The first step, `./footclient --version` might seem unnecessary, but
is needed to ensure we have _some_ profiling data for
`footclient`. Without this, the final link phase will fail.
##### Use the generated PGO data ##### Use the generated PGO data

View file

@ -14,37 +14,70 @@ pkgver() {
} }
build() { build() {
local compiler=other
local do_pgo=no
# makepkg uses -O2 by default, but we *really* want -O3 # makepkg uses -O2 by default, but we *really* want -O3
# -Wno-missing-profile since we're not exercising everything when doing PGO builds CFLAGS+=" -O3"
export CFLAGS+=" -O3 -Wno-missing-profile"
# Figure out which compiler we're using, and whether or not to do PGO
case $(${CC-cc} --version) in
*GCC*)
compiler=gcc
do_pgo=yes
;;
*clang*)
compiler=clang
# We need llvm to be able to manage the profiling data
if command -v llvm-profdata > /dev/null; then
do_pgo=yes
# Meson adds -fprofile-correction, which Clang doesn't
# understand
CFLAGS+=" -Wno-ignored-optimization-argument"
fi
;;
esac
meson --prefix=/usr --buildtype=release --wrap-mode=nofallback -Db_lto=true .. meson --prefix=/usr --buildtype=release --wrap-mode=nofallback -Db_lto=true ..
find -name "*.gcda" -delete if [[ ${do_pgo} == yes ]]; then
meson configure -Db_pgo=generate find -name "*.gcda" -delete
ninja meson configure -Db_pgo=generate
ninja
script_options="--scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel" local script_options="--scroll --scroll-region --colors-regular --colors-bright --colors-256 --colors-rgb --attr-bold --attr-italic --attr-underline --sixel"
tmp_file=$(mktemp) tmp_file=$(mktemp)
if [[ -v WAYLAND_DISPLAY ]]; then if [[ -v WAYLAND_DISPLAY ]]; then
./foot \ ./footclient --version
--config /dev/null \ ./foot \
--term=xterm \ --config /dev/null \
sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}" --term=xterm \
else sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}"
../scripts/generate-alt-random-writes.py \ else
--rows=67 \ ./footclient --version
--cols=135 \ ./foot --version
${script_options} \ ../scripts/generate-alt-random-writes.py \
${tmp_file} --rows=67 \
./pgo ${tmp_file} ${tmp_file} ${tmp_file} --cols=135 \
${script_options} \
${tmp_file}
./pgo ${tmp_file} ${tmp_file} ${tmp_file}
fi
rm "${tmp_file}"
if [[ ${compiler} == clang ]]; then
llvm-profdata merge default_*profraw --output=default.profdata
fi
meson configure -Db_pgo=use
fi fi
rm "${tmp_file}"
meson configure -Db_pgo=use
ninja ninja
} }

View file

@ -35,8 +35,10 @@ static const char *
version_and_features(void) version_and_features(void)
{ {
static char buf[256]; static char buf[256];
snprintf(buf, sizeof(buf), "version: %s %cime", snprintf(buf, sizeof(buf), "version: %s %cime %cpgo",
FOOT_VERSION, feature_ime() ? '+' : '-'); FOOT_VERSION,
feature_ime() ? '+' : '-',
feature_pgo() ? '+' : '-');
return buf; return buf;
} }

View file

@ -10,3 +10,12 @@ static inline bool feature_ime(void)
return false; return false;
#endif #endif
} }
static inline bool feature_pgo(void)
{
#if defined(FOOT_PGO_ENABLED) && FOOT_PGO_ENABLED
return true;
#else
return false;
#endif
}

6
main.c
View file

@ -45,8 +45,10 @@ static const char *
version_and_features(void) version_and_features(void)
{ {
static char buf[256]; static char buf[256];
snprintf(buf, sizeof(buf), "version: %s %cime", snprintf(buf, sizeof(buf), "version: %s %cime %cpgo",
FOOT_VERSION, feature_ime() ? '+' : '-'); FOOT_VERSION,
feature_ime() ? '+' : '-',
feature_pgo() ? '+' : '-');
return buf; return buf;
} }

View file

@ -24,6 +24,9 @@ add_project_arguments(
(get_option('ime') (get_option('ime')
? ['-DFOOT_IME_ENABLED=1'] ? ['-DFOOT_IME_ENABLED=1']
: []) + : []) +
(get_option('b_pgo') == 'use'
? ['-DFOOT_PGO_ENABLED=1']
: []) +
cc.get_supported_arguments( cc.get_supported_arguments(
['-pedantic', ['-pedantic',
'-fstrict-aliasing', '-fstrict-aliasing',
@ -114,16 +117,20 @@ version = custom_target(
output: 'version.h', output: 'version.h',
command: [generate_version_sh, meson.project_version(), '@SOURCE_ROOT@', '@OUTPUT@']) command: [generate_version_sh, meson.project_version(), '@SOURCE_ROOT@', '@OUTPUT@'])
common = static_library(
'common',
'log.c', 'log.h',
'debug.c', 'debug.h',
'xmalloc.c', 'xmalloc.h',
'xsnprintf.c', 'xsnprintf.h'
)
misc = static_library( misc = static_library(
'misc', 'misc',
'debug.c', 'debug.h',
'hsl.c', 'hsl.h', 'hsl.c', 'hsl.h',
'log.c', 'log.h',
'macros.h', 'macros.h',
'misc.c', 'misc.h', 'misc.c', 'misc.h',
'uri.c', 'uri.h', 'uri.c', 'uri.h'
'xmalloc.c', 'xmalloc.h',
'xsnprintf.c', 'xsnprintf.h',
) )
vtlib = static_library( vtlib = static_library(
@ -137,7 +144,7 @@ vtlib = static_library(
wl_proto_src + wl_proto_headers, wl_proto_src + wl_proto_headers,
version, version,
dependencies: [libepoll, pixman, fcft, tllist, wayland_client], dependencies: [libepoll, pixman, fcft, tllist, wayland_client],
link_with: misc, link_with: [common, misc],
) )
pgolib = static_library( pgolib = static_library(
@ -150,13 +157,15 @@ pgolib = static_library(
link_with: vtlib, link_with: vtlib,
) )
executable( if get_option('b_pgo') == 'generate'
'pgo', executable(
'pgo/pgo.c', 'pgo',
wl_proto_src + wl_proto_headers, 'pgo/pgo.c',
dependencies: [math, threads, libepoll, pixman, wayland_client, fcft, tllist], wl_proto_src + wl_proto_headers,
link_with: pgolib, dependencies: [math, threads, libepoll, pixman, wayland_client, fcft, tllist],
) link_with: pgolib,
)
endif
executable( executable(
'foot', 'foot',
@ -192,14 +201,11 @@ executable(
executable( executable(
'footclient', 'footclient',
'client.c', 'client-protocol.h', 'client.c', 'client-protocol.h',
'debug.c', 'debug.h',
'foot-features.h', 'foot-features.h',
'log.c', 'log.h',
'macros.h', 'macros.h',
'util.h', 'util.h',
'xmalloc.c', 'xmalloc.h',
'xsnprintf.c', 'xsnprintf.h',
version, version,
link_with: common,
install: true) install: true)
if tic.found() if tic.found()