Live data from Hacker News

Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

benhoyt.com

51–60 of 234 posts

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#54

This is a rather meaningless comparison, since the differences are going to be dominated by: 1) The choice of libraries/datatypes used for strings and word->count map 2) How the source file is split into words - probably library function again, although in C/C++ one could choose to implement a super-optimized low level version that would blow the others away IMO a performance comparison between languages is only mean…

Agreed. It’s a common desire to boil benchmarks down to a single number.

Some of those languages, however, are far more complex then the others. And as any complex tool, it requires certain methodology. If you are to use heavy machinery like C++, forget iostreams and character-level processing on your hot paths.

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#55
Funny how you can take the "optimized" C++ and make it significantly faster (vs. gnu/linux standard libraries) with little effort. A lookup table for to_lower, instead of bit math, helps slightly. Building with the LLVM-libc string functions helps a lot, because the GNU std::string_view::operator== is calling an AVX-optmized memcmp via the PLT, which is a terrible strategy for short strings. LLVM-libc has an inlined bcmp (note: bcmp can be significantly faster than memcmp, but on GNU they are aliases) that is resolved for the target platform at build time instead of run time.

Edit:

Even if you ignore LLVM-libc, just slapping this into the optimized.cpp and replacing the critical `==` with `our_bcmp` makes it 10% faster. IFUNC calls to micro-optimized SIMD functions are counterproductive. It is far, far better that the compiler can see all the code at build time.

  int our_bcmp (const char* a, const char* b, size_t sz) {
    for (size_t i = 0; i 

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#57
post #32
post #12

I would not call it performance comparison at all. When Python call functions written in C it is not Python's performance. Write those functions using plain Python and then see the results. Sure for this basic example in the article it does not matter from a practical standpoint. But when you need to step away from canned cases suddenly Python's performance sucks big time.

Can we move past the whole "it is not really python to use libraries written in C", especially when talking pure stdlib python? Python is basically a DSL for C extensions. That is the whole point. It would be like criticizing any compiled language for essentially being a DSL for machine code, and not "Real Instructions". Python's ability to interop with pre-built, optimized libraries with a lightweight interface is a…

> It doesn't need to be pointed out …

Apparently there will be someone who feels the need to point it out; and someone who feels the need to point out that it doesn't need to be pointed out; and …

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#58
post #32
post #12

I would not call it performance comparison at all. When Python call functions written in C it is not Python's performance. Write those functions using plain Python and then see the results. Sure for this basic example in the article it does not matter from a practical standpoint. But when you need to step away from canned cases suddenly Python's performance sucks big time.

Can we move past the whole "it is not really python to use libraries written in C", especially when talking pure stdlib python? Python is basically a DSL for C extensions. That is the whole point. It would be like criticizing any compiled language for essentially being a DSL for machine code, and not "Real Instructions". Python's ability to interop with pre-built, optimized libraries with a lightweight interface is a…

[deleted]

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#59
post #32
post #12

I would not call it performance comparison at all. When Python call functions written in C it is not Python's performance. Write those functions using plain Python and then see the results. Sure for this basic example in the article it does not matter from a practical standpoint. But when you need to step away from canned cases suddenly Python's performance sucks big time.

Can we move past the whole "it is not really python to use libraries written in C", especially when talking pure stdlib python? Python is basically a DSL for C extensions. That is the whole point. It would be like criticizing any compiled language for essentially being a DSL for machine code, and not "Real Instructions". Python's ability to interop with pre-built, optimized libraries with a lightweight interface is a…

I am not criticizing Python. It does well enough what it was made to do. It just make no sense to call that particular example a "language performance comparison". It is anything but.

Re: Performance comparison: counting words in Python, C/C++, Awk, Rust, and more

#60

In this type of blog post with comparisons including many languages, you usually see some unatural approach for your favorite language. However, in this case, the Python example is idiomatic. Since the articles calls for better approaches, I would suggest to take the opportunity to use the walrus operator and rsplit() for the optimized version. Something like this: reminding = "" c=Counter( ) while (chunk := sys.stdi…

Your code assumes there is at least one newline in each 64K chunk, and assumes there are no words past the final newline.

It will fail on "abc" and give the wrong answer for "abc\ndef".

I prefer rpartition over rsplit to handle first case, and the loop-and-a-half construct instead of the while+walrus operator to handle the second, as in this modified version of your code:

    remaining = ""
    c=Counter( )
    while True:
        chunk = sys.stdin.read(64 * 1024)
        if not chunk:
            if not remaining:
                break
            pre = post = ""
        else:
            pre, mid, post = chunk.lower().rpartition("\n")
        c.update((remaining + pre).split())
        remaining = post
Post reply on HN