https://gcc.gnu.org/bugzilla/show_bug.cgi?id=91101

            Bug ID: 91101
           Summary: Possible performance regression in libasan with
                    detect_stack_use_after_return=1
           Product: gcc
           Version: 9.1.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: frantisek at sumsal dot cz
                CC: dodji at gcc dot gnu.org, dvyukov at gcc dot gnu.org,
                    jakub at gcc dot gnu.org, kcc at gcc dot gnu.org, marxin at 
gcc dot gnu.org
  Target Milestone: ---

Hello,
in systemd we recently noticed[0], that certain CI's started timeouting after
upgrade to gcc 9.1.0 and 9.1.1. After a bit of investigation it seems that the
runtime of instrumented binaries with ASan is more than doubled. (The GitHub
thread contains claims about the performance issue being present even without
sanitizers, but that hasn't been confirmed yet, so please ignore it).

Also, I apologize if this report is useless for upstream, since it's not using
the trunk GCC, but I'd really like to know if we're doing something
fundamentally wrong or if this is an actual issue. The following report is from
Arch Linux with GCC 9.1.0, but I also managed to reproduce this on Fedora
Rawhide with GCC 9.1.1[1]. As this thread is without any response so far, I've
been trying to collect as much information as possible regarding this issue, as
testing systemd with bleeding-edge software is particularly important for us.

The following statistics provide comparison between two particular systemd test
cases compiled with GCC 8.3.0 (with and without ASan and UBSan) and the same
statistics for GCC 9.1.0:

----

[vagrant@arch build]$ pacman -Q gcc gcc-libs
gcc 8.3.0-1
gcc-libs 8.3.0-1
[vagrant@arch build]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/8.3.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib
--libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info
--with-bugurl=https://bugs.archlinux.org/
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared
--enable-threads=posix --enable-libmpx --with-system-zlib --with-isl
--enable-__cxa_atexit --disable-libunwind-exceptions --enable-clocale=gnu
--disable-libstdcxx-pch --disable-libssp --enable-gnu-unique-object
--enable-linker-build-id --enable-lto --enable-plugin
--enable-install-libiberty --with-linker-hash-style=gnu
--enable-gnu-indirect-function --enable-multilib --disable-werror
--enable-checking=release --enable-default-pie --enable-default-ssp
--enable-cet=auto
Thread model: posix
gcc version 8.3.0 (GCC)

# Basically git clone https://github.com/systemd/systemd /build
[vagrant@arch build]$ meson build-gcc-8.3.0-sanitizers
-Db_sanitize=address,undefined
<...snip...>
[vagrant@arch build]$ meson build-gcc-8.3.0
<...snip...>
[vagrant@arch build]$ ninja -C build-gcc-8.3.0-sanitizers
<...snip...>
[vagrant@arch build]$ ninja -C build-gcc-8.3.0
<...snip...>

# Sanitizer-specific options
[vagrant@arch build]$ export
ASAN_OPTIONS=strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1
[vagrant@arch build]$ export
UBSAN_OPTIONS=print_stacktrace=1:print_summary=1:halt_on_error=1

# WITHOUT sanitizers
[vagrant@arch build]$ /bin/time -v build-gcc-8.3.0/test-conf-parser >/dev/null
<...snip...>
    Command being timed: "build-gcc-8.3.0/test-conf-parser"
    User time (seconds): 1.25
    System time (seconds): 0.01
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.28
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 9944
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 930
    Voluntary context switches: 12
    Involuntary context switches: 107
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

[vagrant@arch build]$ cd build-gcc-8.3.0 && /bin/time -v ../test/hwdb-test.sh
>/dev/null
    Command being timed: "../test/hwdb-test.sh"
    User time (seconds): 0.40
    System time (seconds): 0.01
    Percent of CPU this job got: 98%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.41
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 25752
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 0
    Minor (reclaiming a frame) page faults: 7264
    Voluntary context switches: 71
    Involuntary context switches: 30
    Swaps: 0
    File system inputs: 0
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

# WITH sanitizers
[vagrant@arch build]$ /bin/time -v build-gcc-8.3.0-sanitizers/test-conf-parser
>/dev/null
<...snip...>
    Command being timed: "build-gcc-8.3.0-sanitizers/test-conf-parser"
    User time (seconds): 3.05
    System time (seconds): 0.28
    Percent of CPU this job got: 92%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:03.61
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 347056
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 16
    Minor (reclaiming a frame) page faults: 180270
    Voluntary context switches: 85
    Involuntary context switches: 395
    Swaps: 0
    File system inputs: 35568
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

[vagrant@arch build]$ cd build-gcc-8.3.0-sanitizers/ && /bin/time -v
../test/hwdb-test.sh >/dev/null
    Command being timed: "../test/hwdb-test.sh"
    User time (seconds): 40.08
    System time (seconds): 31.98
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 1:12.41
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 805060
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 3
    Minor (reclaiming a frame) page faults: 22857463
    Voluntary context switches: 97
    Involuntary context switches: 414
    Swaps: 0
    File system inputs: 288
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0


# GCC upgrade
[vagrant@arch build]$ sudo pacman -Sy gcc gcc-libs
...
Packages (2) gcc-9.1.0-2  gcc-libs-9.1.0-2
...
[vagrant@arch build]$ gcc -v
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-pc-linux-gnu/9.1.0/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with: /build/gcc/src/gcc/configure --prefix=/usr --libdir=/usr/lib
--libexecdir=/usr/lib --mandir=/usr/share/man --infodir=/usr/share/info
--with-bugurl=https://bugs.archlinux.org/
--enable-languages=c,c++,ada,fortran,go,lto,objc,obj-c++ --enable-shared
--enable-threads=posix --with-system-zlib --with-isl --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-clocale=gnu --disable-libstdcxx-pch
--disable-libssp --enable-gnu-unique-object --enable-linker-build-id
--enable-lto --enable-plugin --enable-install-libiberty
--with-linker-hash-style=gnu --enable-gnu-indirect-function --enable-multilib
--disable-werror --enable-checking=release --enable-default-pie
--enable-default-ssp --enable-cet=auto
Thread model: posix
gcc version 9.1.0 (GCC)


[vagrant@arch build]$ meson build-gcc-9.1.0-sanitizers
-Db_sanitize=address,undefined
<...snip...>
[vagrant@arch build]$ meson build-gcc-9.1.0
<...snip...>
[vagrant@arch build]$ ninja -C build-gcc-9.1.0-sanitizers
<...snip...>
[vagrant@arch build]$ ninja -C build-gcc-9.1.0
<...snip...>


# WITHOUT sanitizers
[vagrant@arch build]$ /bin/time -v build-gcc-9.1.0/test-conf-parser >/dev/null
<...snip...>
    Command being timed: "build-gcc-9.1.0/test-conf-parser"
    User time (seconds): 1.26
    System time (seconds): 0.00
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:01.28
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 10016
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 1
    Minor (reclaiming a frame) page faults: 928
    Voluntary context switches: 6
    Involuntary context switches: 111
    Swaps: 0
    File system inputs: 96
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

[vagrant@arch build]$ cd build-gcc-9.1.0 && /bin/time -v ../test/hwdb-test.sh
>/dev/null
    Command being timed: "../test/hwdb-test.sh"
    User time (seconds): 0.43
    System time (seconds): 0.03
    Percent of CPU this job got: 95%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.49
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 25856
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 3
    Minor (reclaiming a frame) page faults: 7279
    Voluntary context switches: 108
    Involuntary context switches: 68
    Swaps: 0
    File system inputs: 1144
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

# WITH sanitizers
[vagrant@arch build]$ /bin/time -v build-gcc-9.1.0-sanitizers/test-conf-parser
>/dev/null
<...snip...>
    Command being timed: "build-gcc-9.1.0-sanitizers/test-conf-parser"
    User time (seconds): 30.03
    System time (seconds): 0.33
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:30.50
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 348972
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 17
    Minor (reclaiming a frame) page faults: 180473
    Voluntary context switches: 31
    Involuntary context switches: 160
    Swaps: 0
    File system inputs: 5200
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

[vagrant@arch build]$ cd build-gcc-9.1.0-sanitizers/ && /bin/time -v
../test/hwdb-test.sh >/dev/null
    Command being timed: "../test/hwdb-test.sh"
    User time (seconds): 129.53
    System time (seconds): 32.94
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 2:43.29
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 805868
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 6
    Minor (reclaiming a frame) page faults: 22858160
    Voluntary context switches: 118
    Involuntary context switches: 1136
    Swaps: 0
    File system inputs: 11640
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

----

Notice the huge difference in user/wall time in the ASan+UBsan run, which is
~10 times slower with GCC 9.1.x as opposed to GCC 8.3.0.

However, by switching the `detect_stack_use_after_return` option off, the
performance issue is much less noticeable:

----

[vagrant@arch build]$ export
ASAN_OPTIONS=strict_string_checks=1:check_initialization_order=1:strict_init_order=1:detect_stack_use_after_return=0

[vagrant@arch build]$ /bin/time -v build-gcc-9.1.0-sanitizers/test-conf-parser
>/dev/null
<...snip...>
/tmp/test-conf-parser.Q8S7gi:1: Continuation line too long
    Command being timed: "build-gcc-9.1.0-sanitizers/test-conf-parser"
    User time (seconds): 2.61
    System time (seconds): 0.23
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:02.87
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 347316
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 9
    Minor (reclaiming a frame) page faults: 179814
    Voluntary context switches: 22
    Involuntary context switches: 108
    Swaps: 0
    File system inputs: 1160
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

[vagrant@arch build]$ cd build-gcc-9.1.0-sanitizers/ && /bin/time -v
../test/hwdb-test.sh >/dev/null
    Command being timed: "../test/hwdb-test.sh"
    User time (seconds): 22.71
    System time (seconds): 32.06
    Percent of CPU this job got: 99%
    Elapsed (wall clock) time (h:mm:ss or m:ss): 0:55.11
    Average shared text size (kbytes): 0
    Average unshared data size (kbytes): 0
    Average stack size (kbytes): 0
    Average total size (kbytes): 0
    Maximum resident set size (kbytes): 802892
    Average resident set size (kbytes): 0
    Major (requiring I/O) page faults: 15
    Minor (reclaiming a frame) page faults: 22856894
    Voluntary context switches: 171
    Involuntary context switches: 657
    Swaps: 0
    File system inputs: 25384
    File system outputs: 0
    Socket messages sent: 0
    Socket messages received: 0
    Signals delivered: 0
    Page size (bytes): 4096
    Exit status: 0

---

So far I've failed to convince meson/ninja to build systemd and leave the GCC's
temporary files intact, so I'll provide them as soon as possible.

Thank you.


[0] https://github.com/systemd/systemd/pull/12856#issuecomment-504395847
[1] https://bugzilla.redhat.com/show_bug.cgi?id=1722949

Reply via email to