Live data from Hacker News

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

benhoyt.com

121–130 of 234 posts

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

#121
post #35

surprised to see swift 4 times as slow as non-optimized go. Anyone has an explanation ? I know the swift string type is really complex, but i always assumed it was at least performing well..

Reading anything at all into the relative performance of these programs written by different people which are all doing radically different things seems like a gigantic waste of time. Some of these “simple” versions are custom-specifying allocators to minimize memory overhead and doing highly optimizable ASCII value manipulations and doing byte-equality on strings, rather than go through slower Unicode libraries. The…

i was wondering if this was due to unicode indeed. I had hoped that the benchmarks required languages to perform the same kinds of string check, otherwise there's really no point indeed.

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

#122
post #112

> We usually think of I/O as expensive, but I/O isn’t the bottleneck here...The tokenization and hash table operations are the bottleneck by a long shot Interesting. This is something I'll have to keep in mind. Best practice is always been to consider I/O the slowest. But, it's true... times have changed. Maybe we shouldn't make this assumption anymore.

Here’s a couple of articles on the performance of IO and slowness of other stuff that I find particularly interesting:

https://itnext.io/modern-storage-is-plenty-fast-it-is-the-ap...

https://gregoryszorc.com/blog/2021/04/06/surprisingly-slow/

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

#124

Curious if anyone knows why the swift version is slow? Is it the casting from subsequence to a string?

As I wrote elsewhere in this thread (though I was downvoted), I suspect the reason is that this benchmark is measuring the total execution time of a single run of an executable. This would include any time spent by the executable to bootstrap its runtime environment, initiate a virtual machine, and whatever else it needs to do in addition to the relevant code at hand to process the string.

Such a test will favor implementations that have extremely svelte boostrapping, allowing them to immediately begin executing the relevant code and return a result.

I feel a more useful test would be for the relevant string processing code to be run tens to thousands of times within the process itself, so as to diminish the relative importance of boostrap/warmup code and/or runtime optimization performed by VMs. Unless, of course, part of the intent was specifically to measure the impact of the bootstrapping.

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

#125
post #92

Earlier quoted context omitted.

What happens when the ASCII character for space is embedded within a multibyte UTF-8 codepoint?

Such "overlong" encodings are not valid UTF-8.

This was down-voted, which isn't really the best way to handle things that are wrong

Your parent was wondering about a hypothetical UTF-8 sequence [all sequences in this post are hexadecimal bytes] XX 20 XX in which the ASCII space character encoded 20 is actually somehow part of a UTF-8 character. That's not a thing. UTF-8 is deliberately designed so that nothing like this can happen, along with several other clever properties, such properties are why UTF-8 took over the world.

Overlong sequences are like E0 80 A0 which naively looks like it's a UTF-8 encoding of U+0020 the space character from ASCII but it's not, because U+0020 is encoded as just 20. These encodings are called "overlong" because they're unnecessarily long, they're transporting a bunch of leading zero bits for the Unicode code point, the UTF-8 design says to reject these.

[ If you are writing a decoder you have two sane choices. If your decoder can fail, report an error, etc. you should do that. If it's not allowed to fail (or perhaps there's a flag telling you to press on anyway) each such error should produce the Unicode code point U+FFFD. U+FFFD ("The Replacement Character") is: Visibly obvious (often a white question mark on a black diamond); Not an ASCII character, not a letter, number, punctuation, white space, a magic escape character that might have meaning to some older system, filesystem separator, placeholder or wildcard, or any such thing that could be a problem. Carry on decoding the rest of the supposed UTF-8 after emitting U+FFFD. ]

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

#126
post #124

Curious if anyone knows why the swift version is slow? Is it the casting from subsequence to a string?

As I wrote elsewhere in this thread (though I was downvoted), I suspect the reason is that this benchmark is measuring the total execution time of a single run of an executable. This would include any time spent by the executable to bootstrap its runtime environment, initiate a virtual machine, and whatever else it needs to do in addition to the relevant code at hand to process the string. Such a test will favor impl…

I was going to make a general comment about this too. It’s a huge penalty for Java too and has no correlation for how well it performs outside of toy benchmarks

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

#127
post #124

Curious if anyone knows why the swift version is slow? Is it the casting from subsequence to a string?

As I wrote elsewhere in this thread (though I was downvoted), I suspect the reason is that this benchmark is measuring the total execution time of a single run of an executable. This would include any time spent by the executable to bootstrap its runtime environment, initiate a virtual machine, and whatever else it needs to do in addition to the relevant code at hand to process the string. Such a test will favor impl…

I agree that the benchmark should be run for much longer to get a useful result.

But why does Swift have a long startup time in the first place? Shouldn’t it start near instantly like the C and Rust programs?

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

#128
post #124

Earlier quoted context omitted.

As I wrote elsewhere in this thread (though I was downvoted), I suspect the reason is that this benchmark is measuring the total execution time of a single run of an executable. This would include any time spent by the executable to bootstrap its runtime environment, initiate a virtual machine, and whatever else it needs to do in addition to the relevant code at hand to process the string. Such a test will favor impl…

I agree that the benchmark should be run for much longer to get a useful result. But why does Swift have a long startup time in the first place? Shouldn’t it start near instantly like the C and Rust programs?

I don't think Swift's performance is due to start up time at all. I actually cloned the repo, and ran the benchmark and found that Swift's execution time scales drastically with the size of the input. The Swift team actually boasts about its quick start up time on the official website [1]. I ran a simple hello world benchmark to gauge Swift's start up time and got an output of 13 milliseconds.

  echo 'print("hello world")' > hello.swift && swiftc hello.swift -O -o hello
  time ./hello
[1] https://www.swift.org/server/

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

#130

I love using the UNIX shell (pipes and programs that do "one thing well") to the point where it hurts my ability to improve at other other languages. But sometimes all you need is a throwaway command to do something once, not a beautifully optimized function that will be written, improved, compiled, profiled, reoptimized and then executed a billion times. The utter tersity of a bash one-liner just tickles me.

I'm with you with both shell pipelines and Perl "one-liners". The latter was a wonderful step up from the former back in the 1990s: a modern programming language designed around paving the cowpaths of shell pipelines. The power of both has always been inspiring. So many useful, one-off tasks can be accomplished with a single line in a terminal. So much potential power.

But my problem with both has always been that I needed them often, but not quite often enough to remember them without looking things up (again). Over the years, as my memory of these commands has strengthened, I've needed them less often. We don't use computers the same way we did back then. It's like a spaced repetition system where the spacing is set to guarantee forgetting.

Post reply on HN