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
### Added
### Changed
* Update PGO build instructions in `INSTALL.md`
(https://codeberg.org/dnkl/foot/issues/418).
### Deprecated
### Removed
### Fixed

View file

@ -65,6 +65,7 @@ In addition to the dev variant of the packages above, you need:
* wayland protocols
* ncurses (needed to generate terminfo)
* scdoc (for man page generation)
* llvm (for PGO builds with Clang)
* [tllist](https://codeberg.org/dnkl/tllist) [^1]
A note on compilers; in general, foot runs **much** faster when
@ -184,21 +185,15 @@ slower!) binary.
First, configure the build directory:
```sh
export CFLAGS="$CFLAGS -O3 -Wno-missing-profile"
export CFLAGS="$CFLAGS -O3"
meson --buildtype=release --prefix=/usr -Db_lto=true ../..
```
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.
If you are using Clang instead of GCC, use the following `CFLAGS` instead:
```sh
export CFLAGS="$CFLAGS -O3 \
-Wno-ignored-optimization-argument \
-Wno-profile-instr-out-of-date \
-Wno-profile-instr-unprofiled"
```
Clang users **must** add `-Wno-ignored-optimization-argument` to
`CFLAGS`.
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`:
```sh
./footclient --version
./foot --version
tmp_file=$(mktemp)
../../scripts/generate-alt-random-writes \
--rows=67 \
@ -253,7 +250,12 @@ tmp_file=$(mktemp)
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
`${tmp_file}` in a terminal, youll see random colored characters all
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`:
```sh
./footclient --version
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}
```
You should see a foot window open up, with random colored text. The
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

View file

@ -14,37 +14,70 @@ pkgver() {
}
build() {
local compiler=other
local do_pgo=no
# makepkg uses -O2 by default, but we *really* want -O3
# -Wno-missing-profile since we're not exercising everything when doing PGO builds
export CFLAGS+=" -O3 -Wno-missing-profile"
CFLAGS+=" -O3"
# 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 ..
find -name "*.gcda" -delete
meson configure -Db_pgo=generate
ninja
if [[ ${do_pgo} == yes ]]; then
find -name "*.gcda" -delete
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
./foot \
--config /dev/null \
--term=xterm \
sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}"
else
../scripts/generate-alt-random-writes.py \
--rows=67 \
--cols=135 \
${script_options} \
${tmp_file}
./pgo ${tmp_file} ${tmp_file} ${tmp_file}
if [[ -v WAYLAND_DISPLAY ]]; then
./footclient --version
./foot \
--config /dev/null \
--term=xterm \
sh -c "../scripts/generate-alt-random-writes.py ${script_options} ${tmp_file} && cat ${tmp_file}"
else
./footclient --version
./foot --version
../scripts/generate-alt-random-writes.py \
--rows=67 \
--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
rm "${tmp_file}"
meson configure -Db_pgo=use
ninja
}

View file

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

View file

@ -10,3 +10,12 @@ static inline bool feature_ime(void)
return false;
#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)
{
static char buf[256];
snprintf(buf, sizeof(buf), "version: %s %cime",
FOOT_VERSION, feature_ime() ? '+' : '-');
snprintf(buf, sizeof(buf), "version: %s %cime %cpgo",
FOOT_VERSION,
feature_ime() ? '+' : '-',
feature_pgo() ? '+' : '-');
return buf;
}

View file

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