Earlier quoted context omitted.
Scaling Python on multiple cores is easy: you just run multiple Python processes, each with its own per-core GIL. You are correct, though, that ref-counting overhead is one of the main reasons Python is slow.
The drawback with multiple processes is that they each have all the compiled bytecode on their heap. When I "import nltk" my heap goes from ~12 to ~36 MB. Add a few more dependencies and you end up wasting a non-trivial amount of RAM on python heaps.
Linus Torvalds on Garbage Collection (2002)
91–100 of 207 posts
Re: Linus Torvalds on Garbage Collection (2002)
#92Earlier quoted context omitted.
Scaling Python on multiple cores is easy: you just run multiple Python processes, each with its own per-core GIL. You are correct, though, that ref-counting overhead is one of the main reasons Python is slow.
The drawback with multiple processes is that they each have all the compiled bytecode on their heap. When I "import nltk" my heap goes from ~12 to ~36 MB. Add a few more dependencies and you end up wasting a non-trivial amount of RAM on python heaps.
Re: Linus Torvalds on Garbage Collection (2002)
#93Earlier quoted context omitted.
Linus suggested in the OP that automated reference counting (where the language implementation handles reference counting for the programmer) is preferable to GC. Python uses such reference counting (although it also has a GC fallback to ensure cyclic structures are collected).
And it is one of the reason why python is slow and difficult to scale on multiple cores (the main difficulty by far of removing the GIL is reference counting).
The key to speed is to not share state, which Python can do fine. It's called fork.
Re: Linus Torvalds on Garbage Collection (2002)
#94Here are a couple of reasons why I think it's not so clear cut: 1. If garbage collection was that damaging to the cache, Haskell wouldn't be nearly as fast as C. 2. Copy-on-write data structures are nice because the immutability allows for concurrent access without locking. Granted, this was from 2002 and Linus may no longer feel so strongly about the topic.
Show me a memory-intensive kernel in which Haskell runs close to the performance model. Sparse and dense matrix kernels would be a good place to start. Our C code for sparse matrix-vector products and sparse triangular solves gets better than 90% of STREAM bandwidth (based on an assumption of optimal cache reuse, STREAM is about 85% of hardware peak). Dense matrix kernels should get better than 90% of FPU peak. Unlik…
It's an interesting question though. I'm a Haskell beginner, but I'm pretty experienced with Scala. Let me try to see how using sliding compares with a tight Java loop on statically allocated data for convolutions/filters.
Re: Linus Torvalds on Garbage Collection (2002)
#95Earlier quoted context omitted.
The drawback with multiple processes is that they each have all the compiled bytecode on their heap. When I "import nltk" my heap goes from ~12 to ~36 MB. Add a few more dependencies and you end up wasting a non-trivial amount of RAM on python heaps.
You could do the import and then fork the child processes. That should share all the memory used by the nitk module between all the children (for as long as the memory is not modified by anyone, which triggers a copy-on-write allocation of the affected pages).
Re: Linus Torvalds on Garbage Collection (2002)
#96Earlier quoted context omitted.
That's correct, unless the object is autoreleased, in which case the system will get around to deallocating it after the current run loop iterates (provided you're using the default autorelease pool).
Thank you, that makes sense. So, if I understand this correctly: if one wanted to take advantage of an opportunity to do some cache-friendly reallocation, then avoiding autorelease pools would be necessary.
Re: Linus Torvalds on Garbage Collection (2002)
#97Shortly before Linus wrote this article in 2002, I wrote an XML-RPC library in C that used reference counting. By the time I was done, I'd written 7,000+ lines of extremely paranoid C code, and probably eliminated all the memory leaks. The project cost my client ~$5K. The standard Python xmlrpc library was less than 800 lines of code, and it was probably written in a day or two. Was my library about 50 times faster?…
I Guess Linus also made another suggestion which he didn't pursue on this paragraph: Generational garabage collectors tend to never re-use hot objects, and often do the copying between generations making things even worse on the cache The suggestion? Just reuse hot objects. Note, this post is from 2002. Garbage collectors have improved a lot over the last 9 years. Don't evaluate new technology with such old arguments…
Can you tell us how they have improved in ways that address Linus's specific concerns? And explain how a generational garbage collector can effectively re-use freshly freed objects before they leave the cache? Which 2011 generational GCs take advantage of that idea?
Re: Linus Torvalds on Garbage Collection (2002)
#98Re: Linus Torvalds on Garbage Collection (2002)
#99Earlier quoted context omitted.
You could do the import and then fork the child processes. That should share all the memory used by the nitk module between all the children (for as long as the memory is not modified by anyone, which triggers a copy-on-write allocation of the affected pages).
most forks do copy-on-write and every access to a python object meddles with reference count, which is - you guessed it - a write.
Re: Linus Torvalds on Garbage Collection (2002)
#100Unsurprisngly, things have changed. Many of Linus's complaints were valid, and we've learned how to address them.