[llvm-bugs] [Bug 40763] New: std::cout is more than twice as slow as libstdc++

via llvm-bugs llvm-bugs at lists.llvm.org
Mon Feb 18 09:06:43 PST 2019


https://bugs.llvm.org/show_bug.cgi?id=40763

            Bug ID: 40763
           Summary: std::cout is more than twice as slow as libstdc++
           Product: libc++
           Version: 7.0
          Hardware: Macintosh
                OS: MacOS X
            Status: NEW
          Keywords: performance
          Severity: enhancement
          Priority: P
         Component: All Bugs
          Assignee: unassignedclangbugs at nondot.org
          Reporter: husseydevin at gmail.com
                CC: llvm-bugs at lists.llvm.org, mclow.lists at gmail.com

I saw a lot of people complaining about this on Stack Overflow and the like but
I didn't see any bug reports.

std::cout is at least 2x slower in libc++ than it is in libstdc++. In
libstdc++, std::cout has about the same performance as stdio (and it is faster
with sync_with_stidio(false)), but in libc++, it can be more than 2x slower
than stdio.

Clang 7.0.1 vs GCC 8.2.0 (both from Homebrew)

Source code:

#include <iostream>
#include <cstdio>
#include <chrono>
#include <cstddef>
int main() {
    // true or false, libstdc++ is still much faster than libc++
    std::ios_base::sync_with_stdio(true);

    // sorry I prefer clock()
    auto clock = [] () { return std::chrono::high_resolution_clock::now(); };

    auto start = clock();
    for (std::size_t i = 0; i < 1000; i++) {
        std::cout << i << '\n';
    }
    auto end = clock();
    std::fprintf(stderr, "%llu\n",
std::chrono::duration_cast<std::chrono::microseconds>(end - start).count());

    // show printf for comparison
    start = clock();
    for (std::size_t i = 0; i < 1000; i++) {
        std::printf("%zu\n", i);
    }
    end = clock();

    std::fprintf(stderr, "%llu\n",
std::chrono::duration_cast<std::chrono::microseconds>(end - start).count());
}

Problem:

libc++'s std::cout is twice as slow as libstdc++'s.

~ $ clang++ -O3 bench.cpp -std=c++2a
~ $ ./a.out > /dev/null
690
265

~ $ g++-8 -O3 bench.cpp -std=c++2a
~ $ ./a.out > /dev/null
375
284

To prove it isn't a GCC optimization, I forced Clang to use libstdc++:

~ $ clang++ bench.cpp -O3 -stdlib=libstdc++ -std=c++2a -isystem
/usr/local/opt/gcc/include/c++/8.2.0/ -isystem
/usr/local/opt/gcc/include/c++/8.2.0/x86_64-apple-darwin17.7.0/ -L
/usr/local/opt/gcc/lib/gcc/8 
warning: include path for stdlibc++ headers not found; pass '-stdlib=libc++' on
the command line to use the libc++ standard library instead
[-Wstdlibcxx-not-found]
1 warning generated.
~ $ ./a.out > /dev/null
320
245


Changing sync_with_stdio to false yields cout being faster than printf on
libstdc++, but the same on libc++:

clang++ with libc++:
~ $ ./a.out > /dev/null
697
290

g++ (note: varies a lot)
~ $ ./a.out > /dev/null
164
266

clang++ with libstdc++:
~ $ ./a.out > /dev/null
163
269

Something is clearly off here. Even though stdio has the same performance, the
performance difference is massive.

Note: Xcode 10's Clang has the same effect, and changing the clock printf to
cerr has no effect. 

macOS 10.14.2 Mojave (Mojave Patcher)
2.0 GHz MacBook Pro (15-inch, Early 2011)
8 GB RAM
500 GB SSD
2.0 GHz Intel Core i7 "Sandy Bridge" (2635QM), quad core + HT
clang++ 7.0.2
g++ 8.2.0

-- 
You are receiving this mail because:
You are on the CC list for the bug.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-bugs/attachments/20190218/f04d469e/attachment.html>


More information about the llvm-bugs mailing list