6 ms·
> 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 im
by crabbone 3y ago
> 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 implementations of Lua, Emacs Lisp and Erlang at different times and to various degree. I'm also somewhat familiar with SBCL and ECL, the implementation side. There are different things the authors looked for in these implementations. For example, SBCL emphasizes performance, where ECL emphasizes simplicity and interop with C.
If I had to grade language implementations I've seen, Erlang would absolutely take the cake. It's a very thoughtful and disciplined program where authors went to a great length to design and implement it. CPython is on the lower end of such programs. It's anarchic, very unevenly implemented, you run into comments testifying to the author not knowing what they are doing, what their predecessor did, nor what to do next. Sometimes the code is written from that perspective as well, as in if the author somehow manages to drive themselves in the corner they don't know what the reference count is anymore, they'll just hammer it until they hope all references are dead (well, maybe).
It's the code style that, unfortunately, I associate with proprietary projects where deadlines and cost dictate the quality, where concurrency problems are solved with sleeps, and if that doesn't work, then the sleep delay is doubled. It's not because I specifically hate code being proprietary, but because I meet that kind of code in my day job more than I meet it in hobby open-source projects.
> take a look at the source code for the dict type.
I wrote a Protobuf parser in C with the intention of exposing its bindings to Python. Dictionaries were a natural choice for the hash-map Protobuf elements. I benchmarked my implementation against C++ (Google's) implementation only to discover that std::map wins against Python's dictionary by a landslide.
Maybe Python's dict isn't as bad as most of the rest of the interpreter, but being the best of the worst still doesn't make it good.
- codr7 3y agoExcept 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 comment if you're including Python's VM dispatch in that comparison. What are you trying to prove here?
- JonChesterfield 3y ago(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)
- codr7 3y agoIt's ordered and predictable, which is far from rubbish. In most cases std::unordered_map will be faster, but hashtables have nasty edge cases and are usually more expensive to create. I can pretty much guarantee it's been optimized to hell and back.
- JonChesterfield 3y agoUnordered map sure hasn't been. There are algorithmic performance guarantees in the standard that force the linked list of buckets implementation despite that being slower than alternatives. Maybe the libc++ map<> is a very perfect rbtree, but I doubt that's the state of the art in ordered containers either.
- crabbone 3y agoIf 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.
- JonChesterfield 3y agoPython 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.
- int_19h 3y agoFor 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.
- crabbone 3y agoYou 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's implementation of Protobuf uses std::map for dictionaries, and these dictionaries are exposed to Python. But, following your argument this... shouldn't be possible? To better understand the difference: Python dictionary stores references to Python objects, but it doesn't have to. It could, for example, take Python strings and use C character arrays for storage, and then upon querying the dictionary convert them back to Python str objects. Similarly with integers for example etc. Why is this not done -- I don't know. Knowing how many other things are done in Python, I'd suspect that this isn't done because nobody bothered to do it. It also feels too hard and to unrewarding to patch a single class of objects, even as popular as dictionaries. If you go for this kind of optimizations, you want it to be systematically and uniformly applied to all the code... and that's, I guess, how Cython came to be, for example.
- int_19h 3y agoCython 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.