Live data from Hacker News

Rust std fs slower than Python? No, it's hardware

xuanwo.io

231–240 of 255 posts

Re: Rust std fs slower than Python? No, it's hardware

#231
post #150

Earlier quoted context omitted.

> Have you ever attempted to write a scripting language that performs better? No, because "scripting language" is not a thing. But, if we are talking about implementing languages, then I worked with many language implementations. The most comparable one that I know fairly well, inside-and-out would be the AVM, i.e. the ActionScript Virtual Machine. It's not well-written either unfortunately. I've looked at implementa…

Except it is, because everyone knows sort of what it means, an interpreted language that prioritizes convenience over performance; Perl/Python/Ruby/Lua/PHP/etc. SBCL is definitely a different beast. I would expect Emacs Lisp & Lua to be more similar. Erlang had plenty more funding and stricter requirements. C++'s std::map has most likely gotten even more attention than Python's dict, but I'm not sure from your commen…

> interpreted language

There is no such thing as interpreted language. A language implementation can be called an interpreter to emphasize the reliance on rich existing library, but there's no real line here that can divide languages into two non-ambiguous categories. So... is C an "interpreted language"? -- well, under certain light it is, since it calls into libc for a lot of functionality, therefor libc can be thought of as its interpreter. Similarly, machine code is often said to be interpreted by the CPU, when it translates it to microcode and so on.

> prioritizes convenience over performance

This has nothing to do with scripting. When the word "scripting" is used, it's about the ability to automate another program, and record this automation as a "script". Again, this is not an absolute metric that can divide all languages or their implementations into scripting and not-scripting. When the word "scripting" is used properly it is used to emphasize the fact that a particular program is amenable to automation by means of writing other programs, possibly in another language.

Here are some fun examples to consider. For example, MSBuild, a program written in C# AFAIK, can be scripted in C# to compile C# programs! qBittorrent, a program written in Python can be scripted using any language that has Selenium bindings because qBittorrent uses Qt for the GUI stuff and Qt can be automated using Selenium. Adobe Photoshop (used to be, not sure about now) can be scripted in JavaScript.

To give you some examples which make your claim ridiculously wrong: Forth used to be used in Solaris bootloader to automate kernel loading progress, i.e. it was used as a scripting language for that purpose, however most mature Forth implementations are aiming for the same performance bracket as C. You'd be also hard-pressed to find a lot of people who think that Forth is a very convenient language... (I do believe it's fine, but there may be another five or so people who believe it too).

---

Basically, your ideas about programming language taxonomies are all wrong and broken... sorry. Not only you misapplied the labels, you don't even have any good labels to begin with.

Anyways,

> What are you trying to prove here?

Where's here? Do you mean the original comment or the one that mentions std::map?

If the former: I'm trying to prove that CPython is a dumpster fire of a program. That is based on many years of working with it and quite extensive knowledge of its internals of which I already provided examples of.

If it is the later: parent claimed something about how optimized Python's dictionary is, I showed that it has a very long way to go to be in the category of good performers. I.e. optimizing something, no matter how much, doesn't mean that it works well.

I don't know what do you mean by Python's VM dispatch in this context. I already explained that I used Python C API for dictionaries, namely this: https://docs.python.org/3/c-api/dict.html . It's very easy to find equivalent functionality in std::map.

Re: Rust std fs slower than Python? No, it's hardware

#232
post #150

Earlier quoted context omitted.

Except it is, because everyone knows sort of what it means, an interpreted language that prioritizes convenience over performance; Perl/Python/Ruby/Lua/PHP/etc. SBCL is definitely a different beast. I would expect Emacs Lisp & Lua to be more similar. Erlang had plenty more funding and stricter requirements. C++'s std::map has most likely gotten even more attention than Python's dict, but I'm not sure from your commen…

(std::map is famously rubbish, to the extent that a common code review fix is to replace it with std::unordered_map. Map is a tree, unordered map is a linked-list-collision hashtable. Both are something of a performance embarrassment for C++. So std::map outperforming a given hashtable is a strongly negative judgement)

If I may hazard a guess (I don't know why the original code used it), Python dictionaries are also ordered (and there's no option in Python's library to have them not ordered). Maybe they wanted to match Python's behavior.

Re: Rust std fs slower than Python? No, it's hardware

#233

Earlier quoted context omitted.

(std::map is famously rubbish, to the extent that a common code review fix is to replace it with std::unordered_map. Map is a tree, unordered map is a linked-list-collision hashtable. Both are something of a performance embarrassment for C++. So std::map outperforming a given hashtable is a strongly negative judgement)

If I may hazard a guess (I don't know why the original code used it), Python dictionaries are also ordered (and there's no option in Python's library to have them not ordered). Maybe they wanted to match Python's behavior.

Python dicts are ordered in a slightly weird way though, and only since 3.6 (before that it leaked the hashtable implementation scheme). Std::map orders things by some boolean comparator (and duly goes wrong if you give it a partial order comparison), binary tree style. Python currently orders by insertion order, very like storing a list of the keys as well as a hash table, so it can iterate over it in insertion order. That's definitely slower than not maintaining that order but it seems popular with python developers.

Re: Rust std fs slower than Python? No, it's hardware

#234

Earlier quoted context omitted.

We're not talking about random changes. We're talking about paying attention to the measured performance of changes made for other reasons. Just like in this article. The author measured, wondered, investigated, experimented, and finally, after a lot of hard work, made the C/Rust programs faster. You wouldn't call that luck, would you? If there had been a similar performance regression in CPython, then a benchmark co…

You can look at the history of PyObject yourself: https://github.com/python/cpython/commits/main/Include/objec... . None of these changes were done because of weird CPU errata that meant that making the header bigger was a performance win. That isn't to say that the developers wouldn't be interested in such effects, or be able to detect them, but the fact that the object header happens to be large enough to avoid the…

What you don't see in the logs are the experiments and branches that weren't pursued further because they didn't perform well enough.

Also: If you're going to prove that changes informed by performance measurements are absent from the commit logs, then you'll need to look in the logs for all the relevant places, which means also looking at I/O and bytes and allocator code.

Re: Rust std fs slower than Python? No, it's hardware

#235
post #218

Earlier quoted context omitted.

Some quick searching gives that FSRM is used for at least 128 bytes or so (ERMS for ≥~2048 bytes for reference); in base x86 (i.e. SSE2) that's 8 loads & 8 stores, ~62 bytes of code. At that point calling into a library function isn't too unreasonable (at the very least it could utilize AVX and cut that in half to 4 loads+4 stores, though at the cost of function call overhead & some (likely correctly-predicted) branc…

https://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git/... Suggests that it should be usable for even shorter copies. And that's really my point. We should have One True memcpy instruction sequence that we use everywhere and stop worrying. And yet...

Unfortunately, we can't change the past, and seemingly in the past it wasn't worth it to have a fast One True memcpy (and perhaps to a decent extent still isn't). I'm still typing this on a Haswell CPU, which don't have FSRM (rep movsb of 16 bytes in a loop takes ~10ns=36 cycles per iteration avg).

But, yeah it does seem that my 128 bytes of a quick search was wrong. (though, gcc & clang for '-march=alderlake' both never generate 'rep movsb' on '-O3'; on `-Os` gcc starts giving a rep movsb for ≥65B, clang still never does)

Re: Rust std fs slower than Python? No, it's hardware

#236

Earlier quoted context omitted.

I wonder if its because we're sometimes talking cross purposes. For me, coding is almost exclusively using python libraries like numpy to call out to other languages like c or FORTRAN. It feels silly to say I'm not coding in Python to me. On the other hand, if you're writing those libraries, coding to you is mostly writing FORTRAN and c optimizations. It probably feels silly to say you're coding in Python just becaus…

There is a version of BASIC, a QuickBasic clone called Qb64 that is lightning fast because it transpiles to C++. By your admission a programmer should think that BASIC is fast because he only does BASIC and does not care about the environment details? It's actually the opposite, a Python programmer should know how to offload most, or use the libraries that do so, out of Python into C. He should not be oblivious to th…

I think maybe it's just semantics as long as everyone agrees where the speedup is happening (at the low level language calls).

I noticed that you're pretty hard in the "basic isn't fast, the thing it transpiles to is fast" camp, but still accidentally said "there is a version of BASIC [...] that is lightning fast" which I'm not sure you think? Highlights just how tricky it is to talk about where speed lives

Re: Rust std fs slower than Python? No, it's hardware

#237

There are two dedicated CPU feature flags to indicate that REP STOS/MOV are fast and usable as short instruction sequence for memset/memcpy. Having to hand-roll optimized routines for each new CPU generation has been an ongoing pain for decades. And yet here we are again. Shouldn't this be part of some timing testsuite of CPU vendors by now?

I'm completely making stuff up here, but I wonder if this is the effect of some last minute (or even post-release, via ucode update) bug fix, where page aligned fast rep movs had issues or were subject to some attack and got disabled.

Then fast rep movs should have been disabled in cpuid altogether

Re: Rust std fs slower than Python? No, it's hardware

#238

Earlier quoted context omitted.

The exact nature of the fix is unclear at present. During dynamic linking, glibc picks a memcpy implementation which seems most appropriate for the current machine. We have about 13 different implementations just for x86-64. We could add another one for current(ish) AMD CPUs, select a different existing implementation for them, or change the default for a configurable cutover point in a parameterized implementation.

This code is in the kernel, so dynamic linking and glibc is not really relevant.

Admittedly I had missed that.

The kernel has self-patching mechanisms for doing effectively the same thing (although I don't know if it has ever been applied to memcpy before).

Re: Rust std fs slower than Python? No, it's hardware

#239
post #41

The article itself is a great read and it has fascinating info related to this issue. However I am more interested/concerned about another part. How the issue is reported/recorded and how the communications are handled. Reporting is done over discord, which is a proprietary environment which is not indexed, or searchable. Will not be archived. Communications and deliberations are done over discord and telegram, which…

Yes, they are proprietary, which is not great. But I don't buy the allegation that they are not indexed or searchable. There are very few IMs that provide builtin publicly accessable log indexed or searchable by default. Does every IRC server come with public log? What about Matrix groups? How do discussion there not get lost in timeline? You can provide public log of them not because they are not proprietary, but th…

This is not a way to have bug discussions, or record them. Do you really think I could find this information on a search for a similar issue?

Only thing that makes this bug and the process of the debug visible is this blog post.

Another point is I don't think IRC or any instant messaging app is the correct place for this kinds of discussions. Unless important points are logged to some bug reporting tool, or perhaps a mailing list, or to a blog post like this one, they are useless for historic purposes.

Re: Rust std fs slower than Python? No, it's hardware

#240

Earlier quoted context omitted.

For starters, since everything in Python is a pass-by-ref object, dicts store pointers to values, which then have to be allocated on the heap and refcounted, whereas std::map can store values directly. But this is the consequence of a very-high-level object model used by CPython, not its dict implementation that has to adapt to that.

You are very confused between how something works right now and how it can work in principle. In this you very much resemble CPython developers: they never attempt optimizations that go beyond what Python C API can offer. This is very limiting (and, this is why all sorts of Python JIT compilers can in many circumstances beat CPython by a lot). The evidence to how absurd your claim is is right in front of you: Google'…

Cython is pretty much Python without bytecode interpreter, translated to C instead, but retaining the object model. That's why it's so slow.

And the reason why the object model is the way it is, is because it's an entrenched part of the Python ABI. Sure, if you break that, you can do things a lot faster - this isn't news, people have been doing this with projects like Jython and IronPython that can work a lot faster. But the existing ecosystem of packages is so centered on CPython that this approach has proven to be self-defeating - you end up with a Python implementation that very few people actually use.

So, no, it's not because people are "very confused" or "nobody bothered to do it". It's because compatibility matters.

Post reply on HN