public inbox for gcc-bugs@sourceware.org
help / color / mirror / Atom feed
* [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
@ 2020-09-28 13:34 mail at milianw dot de
  2020-09-29 15:15 ` [Bug sanitizer/97229] " marxin at gcc dot gnu.org
                   ` (5 more replies)
  0 siblings, 6 replies; 7+ messages in thread
From: mail at milianw dot de @ 2020-09-28 13:34 UTC (permalink / raw)
  To: gcc-bugs

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

            Bug ID: 97229
           Summary: pointer-compare sanitizer is very slow due to
                    __asan::IsAddressNearGlobal
           Product: gcc
           Version: 10.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: sanitizer
          Assignee: unassigned at gcc dot gnu.org
          Reporter: mail at milianw dot de
                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: ---

I am trying to use the pointer-compare sanitizer during product development. I
noticed that it is usually fine from a performance POV, but one specific code
path is getting extremely slow. Quasi 99% of the CPU samples point at this
backtrace:

```
<our code>
__sanitizer_ptr_cmp
__asanCheckForInvalidPointerPair
__asanCheckForInvalidPointerPair
__asan::IsInvalidPointerPair
__asan::GetGlobalAddressInformation(unsigned long, unsigned long, ...)
__asan::GetGlobalsForAddress(unsigned long, __asan_global*, ...)
__asan::isAddressNearGlobal
```

I have tried to simulate what our code does in this simplistic example: It
copies one file to another in a stupid way via mmap. The pointer comparison is
within the copy() function below.

```
#include <cstdio>
#include <fcntl.h>
#include <unistd.h>
#include <sys/mman.h>

#include <algorithm>

static
__attribute__((noinline))
void copy(const unsigned char *source, size_t source_size,
          unsigned char *target, size_t target_size)
{
    if (target + source_size > target + target_size) {
        fprintf(stderr, "bad offsets: %zu %zu\n", target_size, source_size);
        return;
    }
    std::copy_n(source, source_size, target);
}

unsigned char* mapBuffer(const char *path, size_t size)
{
    auto fd = open(path, O_CREAT | O_RDWR, 0600);
    if (fd == -1) {
        perror("failed to open file");
        return nullptr;
    }

    if (posix_fallocate64(fd, 0, size) != 0) {
        perror("failed to resize file");
        close(fd);
        return nullptr;
    }

    auto buffer = mmap(nullptr, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd,
0);
    close(fd);

    if (!buffer) {
        perror("failed to mmap file");
        return nullptr;
    }

    return reinterpret_cast<unsigned char*>(buffer);
}

int main(int argc, char **argv)
{
    if (argc != 3) {
        fprintf(stderr, "USAGE: ./a.out BUFFER_SIZE COPY_SIZE\n");
        return 1;
    }

    const auto size_i = atoi(argv[1]);
    if (size_i < 0) {
        fprintf(stderr, "bad size: %d\n", size_i);
        return 1;
    }
    const auto size = static_cast<size_t>(size_i);

    const auto copySize_i = atoi(argv[2]);
    if (copySize_i < 0 || copySize_i > size_i || (size_i % copySize_i) != 0) {
        fprintf(stderr, "bad copy size: %d %d\n", copySize_i, size_i);
        return 1;
    }
    const auto copySize = static_cast<size_t>(copySize_i);

    auto source = mapBuffer("/tmp/source.dat", size);
    if (!source) {
        return 1;
    }

    auto target = mapBuffer("/tmp/target.dat", size);
    if (!target) {
        return 1;
    }

    for (int i = 0; i < size; i += copySize) {
        copy(source + i, copySize, target + i, copySize);
    }

    munmap(source, size);
    munmap(target, size);
    return 0;
}
```

But that demo does not show the extreme slow down. It is actually behaving
quite well, at most 10% slow down, when enabling pointer-compare with the
ASAN_OPTIONS env var.

In the real application, the slow-down is more in the order of 100x or more.
That app links in a lot of other libraries and also runs code in multiple
threads, so I suspect that the issue I'm seeing is related to the amount of
globals and potentially libraries available in the application?  Any idea how I
could reproduce this to create a proper MWE?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
@ 2020-09-29 15:15 ` marxin at gcc dot gnu.org
  2020-09-30 13:26 ` mail at milianw dot de
                   ` (4 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-09-29 15:15 UTC (permalink / raw)
  To: gcc-bugs

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

Martin Liška <marxin at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2020-09-29
           Assignee|unassigned at gcc dot gnu.org      |marxin at gcc dot gnu.org
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |ASSIGNED

--- Comment #1 from Martin Liška <marxin at gcc dot gnu.org> ---
Thank you Millian for the report. I'm the author of the pointer-compare
run-time implementation and I can help.

Can you please paste 'perf report' of your real application. I bet you have
quite some globals and we stupidly iterate over them here:
https://github.com/gcc-mirror/gcc/blob/master/libsanitizer/asan/asan_globals.cpp#L108-L127

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
  2020-09-29 15:15 ` [Bug sanitizer/97229] " marxin at gcc dot gnu.org
@ 2020-09-30 13:26 ` mail at milianw dot de
  2020-10-02  9:48 ` marxin at gcc dot gnu.org
                   ` (3 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: mail at milianw dot de @ 2020-09-30 13:26 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #2 from Milian Wolff <mail at milianw dot de> ---
As I said, >99% of the samples point to this backtrace:

```
<our code>
__sanitizer_ptr_cmp
__asanCheckForInvalidPointerPair
__asanCheckForInvalidPointerPair
__asan::IsInvalidPointerPair
__asan::GetGlobalAddressInformation(unsigned long, unsigned long, ...)
__asan::GetGlobalsForAddress(unsigned long, __asan_global*, ...)
__asan::isAddressNearGlobal
```

if you want per-line cost attribution, I'd first have to compile the sanitizer
runtime with debug symbols.

If you really need the `perf report` output instead (why?) I can redo the
measurement again.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
  2020-09-29 15:15 ` [Bug sanitizer/97229] " marxin at gcc dot gnu.org
  2020-09-30 13:26 ` mail at milianw dot de
@ 2020-10-02  9:48 ` marxin at gcc dot gnu.org
  2020-10-02  9:50 ` marxin at gcc dot gnu.org
                   ` (2 subsequent siblings)
  5 siblings, 0 replies; 7+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-10-02  9:48 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #3 from Martin Liška <marxin at gcc dot gnu.org> ---
Created attachment 49298
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49298&action=edit
Reduced test-case

There's reduced test-case:

$ gcc pointer-cmp.c -fsanitize=address,pointer-compare &&
ASAN_OPTIONS="detect_invalid_pointer_pairs=2" perf record ./a.out
$ perf report --stdio
...
    95.22%  a.out    libasan.so.6.0.0    [.] __asan::GetGlobalsForAddress
     2.13%  a.out    libasan.so.6.0.0    [.] __sanitizer::internal_memcpy
     0.75%  a.out    libasan.so.6.0.0    [.] __sanitizer::BlockingMutex::Lock
     0.60%  a.out    libasan.so.6.0.0    [.] __sanitizer::BlockingMutex::Unlock

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
                   ` (2 preceding siblings ...)
  2020-10-02  9:48 ` marxin at gcc dot gnu.org
@ 2020-10-02  9:50 ` marxin at gcc dot gnu.org
  2020-10-02  9:51 ` marxin at gcc dot gnu.org
  2020-10-02  9:53 ` marxin at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-10-02  9:50 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #4 from Martin Liška <marxin at gcc dot gnu.org> ---
I've got a hackish patch that tries to resolve that.
Basically, linear iteration of globals is very slow and a better data structure
should be used (I used sorted list), so each lookup is at least O(log N).
I'm going to report that to upstream.

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
                   ` (3 preceding siblings ...)
  2020-10-02  9:50 ` marxin at gcc dot gnu.org
@ 2020-10-02  9:51 ` marxin at gcc dot gnu.org
  2020-10-02  9:53 ` marxin at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-10-02  9:51 UTC (permalink / raw)
  To: gcc-bugs

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

--- Comment #5 from Martin Liška <marxin at gcc dot gnu.org> ---
Created attachment 49299
  --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=49299&action=edit
Hackish patch candidate

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [Bug sanitizer/97229] pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal
  2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
                   ` (4 preceding siblings ...)
  2020-10-02  9:51 ` marxin at gcc dot gnu.org
@ 2020-10-02  9:53 ` marxin at gcc dot gnu.org
  5 siblings, 0 replies; 7+ messages in thread
From: marxin at gcc dot gnu.org @ 2020-10-02  9:53 UTC (permalink / raw)
  To: gcc-bugs

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

Martin Liška <marxin at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|ASSIGNED                    |WAITING
                URL|                            |https://github.com/google/s
                   |                            |anitizers/issues/1324

--- Comment #6 from Martin Liška <marxin at gcc dot gnu.org> ---
Waiting for an upstream fix.

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2020-10-02  9:53 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-09-28 13:34 [Bug sanitizer/97229] New: pointer-compare sanitizer is very slow due to __asan::IsAddressNearGlobal mail at milianw dot de
2020-09-29 15:15 ` [Bug sanitizer/97229] " marxin at gcc dot gnu.org
2020-09-30 13:26 ` mail at milianw dot de
2020-10-02  9:48 ` marxin at gcc dot gnu.org
2020-10-02  9:50 ` marxin at gcc dot gnu.org
2020-10-02  9:51 ` marxin at gcc dot gnu.org
2020-10-02  9:53 ` marxin at gcc dot gnu.org

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).