5 ms·
Something not unlike this happened to me when moving some batch processing code from C++ to Python 1.4 (this was 1997). The batch started finishing about 10x fa
by rented_mule 7mo ago
Something not unlike this happened to me when moving some batch processing code from C++ to Python 1.4 (this was 1997). The batch started finishing about 10x faster. We refused to believe it at first and started looking to make sure the work was actually being done. It was.
The port had been done in a weekend just to see if we could use Python in production. The C++ code had taken a few months to write. The port was pretty direct, function for function. It was even line for line where language and library differences didn't offer an easier way.
A couple of us worked together for a day to find the reason for the speedup. Just looking at the code didn't give us any clues, so we started profiling both versions. We found out that the port had accidentally fixed a previously unknown bug in some code that built and compared cache keys. After identifying the small misbehaving function, we had to study the C++ code pretty hard to even understand what the problem was. I don't remember the exact nature of the bug, but I do remember thinking that particular type of bug would be hard to express in Python, and that's exactly why it was accidentally fixed.
We immediately started moving the rest of our back end to Python. Most things were slower, but not by much because most of our back end was i/o bound. We soon found out that we could make algorithmic improvements so much more quickly, so a lot of the slowest things got a lot faster than they had ever been. And, most importantly, we (the software developers) got quite a bit faster.
- envguard 7mo ago[flagged]
- sincerely 7mo agoAI account
- DaleBiagio 7mo ago[dead]
- apitman 7mo agoI don't think the better software part is playing out
- ch4s3 7mo agoThere’s a lot of really great software out there right now, and a lot that’s terrible and I think powerful abstractions enable both.
- remexre 7mo agoyou're thinking of the programs in low-level langs that survived their higher-level-lang competitors; if you plot the programs on your machine by age, how does the low quartile compare on reliability between programs written in each group
- DaleBiagio 7mo agoSurvivorship bias is exactly right. The C and assembly programs we still use are the ones that were good enough to last. The thousands that weren't are gone. Nobody counts the programs that were never finished because the language made them too hard to write in the first place.
- samiv 7mo agoUntil at some point in a language like python all the things that allowed you write software faster start to slow you down like the lack of static typing and typing errors and spending time figuring out whether foo method works with ducks or quacks or foovars or whether the latest refactoring actually silently broke it because now you need bazzes instead of ducks. Yeah.
- furyofantares 7mo agoThanks, Programming History Facts Bot I was not actually sure this one was a bot, despite LLM-isms and, sadly, being new. But you can look at the comment history and see.
- DaleBiagio 7mo agoDefinitely not a bot, I am however super interested in programming history!
- Aurornis 7mo agoThis comment comes from a bot account. One of the more clever ones I’ve seen that avoids some of the usual tells, but the comment history taken together exposes it. I hit the flag button on the comment and suggest others do too.
- DaleBiagio 7mo agoHuh? How am I a bot account?
- asa400 7mo agoFun story! Performance is often highly unintuitive, and even counterintuitive (e.g. going from C++ to Python). Very much an art as well as a science. Crazy how many stories like this I’ve heard of how doing performance work helped people uncover bugs and/or hidden assumptions about their systems.
- staticassertion 7mo agoIt doesn't come off as unintuitive by my read. They had a bug that led to a massive performance regression. Rewriting the code didn't have that bug so it led to a performance improvement. They found that they had fewer bugs in Python so they continued with it.
- harpiaharpyja 7mo agoI think a lot of people (especially those who are only peripherally involved in development, like management) don't really consider performance regressions at all when thinking about how to get software to go faster. Meanwhile my experience has been that whenever there has been a performance issue severe enough to actually matter, it's often been the result of some kind of performance bug, not so much language, runtime, or even algorithm choices for that matter. Hence whenever the topic of how to improve performance comes up, I always, always insist that we profile first.
- staticassertion 7mo agoMy experience has been that performance bugs show up in lots of places and I'm very lucky when it's just a bug. The far more painful performance issues are language and runtime limitations. But, of course, profiling is always step one.
- deleted 7mo ago[deleted]
- asveikau 7mo ago> After identifying the small misbehaving function, we had to study the C++ code pretty hard to even understand what the problem was. I don't remember the exact nature of the bug, but I do remember thinking that particular type of bug would be hard to express in Python, and that's exactly why it was accidentally fixed. Pure speculation, but I would guess this has something to do with a copy constructor getting invoked in a place you wouldn't guess, that ends up in a critical path.
- NooneAtAll3 7mo agogood ol' shallow-vs-deep copy
- andrewflnr 7mo agoGiven the context, I'm thinking bad cache keys resulting in spurious cache misses, where the keys are built in some low-level way. Cache misses almost certainly have a bigger asymptotic impact than extra copies, unless that copy constructor is really heavy.
- asveikau 7mo agoI'm just remembering a performance issue I heard of eons ago where a sorting function comparison callback inadvertently allocated memory. It made sorting very slow. Someone said in a meeting that sorting was slow, and we all had a laugh about "shouldn't have used the bubble sort!" But it was the key comparison doing something stupid.
- branko_d 7mo agoMy guess would be bad hashing, resulting in too many collisions.
- ameixaseca 7mo agoMy experience is the exact opposite. This was particularly true for one of the projects I've worked with in the past, where Python was chosen as the main language for a monitoring service. In short, it proved itself to be a disaster: just the Python process collecting and parsing the metrics of all programs consumed 30-40% of the processing power of the lower end boxes. In the end, the project went ahead for a while more, and we had to do all sorts of mitigations to get the performance impact to be less of an issue. We did consider replacing it all by a few open source tools written in C and some glue code, the initial prototype used few MBs instead of dozens (or even hundreds) of MBs of memory, while barely registering any CPU load, but in the end it was deemed a waste of time when the whole project was terminated.
- serial_dev 7mo agoAnother anecdote, the team couldn’t improve concurrency reliably in Python, they rewrote the service in about a month (ten years ago) in Go, everything ran about 20x faster.
- wiseowise 7mo ago> but in the end it was deemed a waste of time when the whole project was terminated. The main lesson of the story. Just pick Python and move fast, kids. It doesn’t matter how fast your software is if nobody uses it.
- stephantul 7mo agoThis is it. Getting something on the table for stakeholders to look at trumps anything else.
- shevy-java 7mo ago[flagged]
- ameixaseca 7mo agoIt would have taken the same time, if not less, given the extra time for mitigations, trying different optimization techniques, runtimes, etc. One of the reasons the project was killed was that we couldn't port it to our line of low powered devices without a full rewrite in C. Please note this was more than a decade ago, way before Rust was the language it was today. I wouldn't chose anything else besides Rust today since it gives the best of both worlds: a truly high level language with low level resource controls.
- tda 7mo agoOme advantage of python is that it is so slow that if you choose the wrong algorithm or data structure that soon gets obvious. And for complicated stuff this is exactly where I find the LLMs struggle. So I make a first version in Python, and only when I am happy with the results and the speed feels reasonable compared to the problem complexity, I ask Claude Code to port the critical parts to Rust.
- rabisg 7mo agoThe last part is really interesting. It feels like the whole world will soon become Python/JS because thats what LLMs are good at. Very few people will then take the pain of optimizing it
- eru 7mo agoThe LLMs are pretty good at optimising. Not because they are brilliant, but because they are pretty good at throwing pretty much all known techniques at a problem. And they also don't tire of profiling and running experiments.
- elcritch 7mo agoNot just profiling, but decoding protocols too. Recently I tried Codex/GPT5 with updating a bluetooth library for batteries and it was able to start capturing bluetooth packets and comparing them with the libraries other models. It was indefatigable. I didn't even know if was so easy to capture BLE packets.
- shevy-java 7mo ago> We immediately started moving the rest of our back end to Python. Most things were slower, but not by much because most of our back end was i/o bound. Would be kind of cool if e. g. python or ruby could be as fast as C or C++. I wonder if this could be possible, assuming we could modify both to achieve that as outcome. But without having a language that would be like C or C++. Right now there is a strange divide between "scripting" languages and compiled ones.
- nubg 7mo ago@dang this is an ai slop account, check his other comments
- peter_retief 7mo agoI suspect that you used highly optimized algorithms written for python, like the vector algorithms in numpy? You will struggle to write better code, at least I would.
- masklinn 7mo agoPython 1.4 would be mid-late 90s long before numpy and vector algorithms would have been available. I suspect it’s more likely to be something like passing std::string by value not realising that would copy the string every time, especially with the statement that the mistake would be hard to express in Python.
- johnisgood 7mo agoEverything is new to the uninitiated. :P
- WalterBright 7mo ago> We soon found out that we could make algorithmic improvements so much more quickly It's true that writing code in C doesn't automatically make it faster. For example, string manipulation. 0-terminated strings (the default in C) are, frankly, an abomination. String processing code is a tangle of strlen, strcpy, strncpy, strcat, all of which require repeated passes over the string looking for the 0. (Even worse, reloading the string into the cache just to find its length makes things even slower.) Worse is the problem that, in order to slice a string, you have to malloc some memory and copy the string. And then carefully manage the lifetime of that slice. The fix is simple - use length-delimited strings. D relies on them to great effect. You can do them in C, but you get no succor from the language. I've proposed a simple enhancement for C to make them work https://www.digitalmars.com/articles/C-biggest-mistake.html https://www.digitalmars.com/articles/C-biggest-mistake.html but nobody in the C world has any interest in it (which baffles me, it is so simple!). Another source of slowdown in C is I've discovered over the years that C is not a plastic language, it is a brittle one. The first algorithm you select for a C project gets so welded into it that it cannot be changed without great difficulty. (And we all know that algorithms are the key to speed, not coding details.) Why isn't C plastic? It's because one cannot switch back and forth between a reference type and a value type without extensively rewriting every use of it. For example: struct S { int a; } int foo(struct S s) { return s.a; } int bar(struct S *s) { return s->a; } If you want to switch between reference and value, you've got to go through all your code swapping . and ->. It's just too tedious and never happens. In D: struct S { int a; } int foo(S s) { return s.a; } int bar(S *s) { return s.a; } I discovered while working on D that there is no reason for the C and C++ -> operator to even exist, the . operator covers both bases!
- garaetjjte 7mo agoWell clearly there is use for these - how do you distinguish what you are accessing in smart-pointer-like types.
- WalterBright 7mo agoYou'd still use the "." operator. Value, reference, or smart pointer use the same syntax. This means you can refactor them easily.
- zeroonetwothree 7mo agoI ported Python to C++ one time and it ran 10c faster with 10x less memory usage with no architectural changes
- casey2 7mo agoThis is the difference between scripting and programming. If you use C++ as a scripting language you're gonna have a bad time.Of course a scripting language is faster for scripting! That doesn't mean you go full Graham and throw away real programming languages, it just means you aren't writing systems software. The usual strategy is to write a script then if it's slow see how you could design a program that would The usual strategy in the real world is to copy paste thousands of lines of C++ code until someone comes along and writes a proper direct solution to the problem. Of course there are ideas on how to fix this, either writing your own scripting libraries (stb), packages (go/rust/ts), metaprogramming (lisp/jai). As for bugs those are a function of how you choose to write code, the standard way of writing shell it bug prone, the standard way of writing python is less so, not using overloading & going wider in c++ generally helps.
- deterministic 7mo agoI use C++ instead of so called 'scripting' languages all the time. I have zero problems doing that and it is lightning fast.