3 ms·
If starting today, I'd probably try to use Rust. However, using Python actually makes it much lighter weight than it would be running all native code, because
by dmbaggett 11y ago
If starting today, I'd probably try to use Rust.
However, using Python actually makes it much lighter weight than it would be running all native code, because Python bytecode is quite compact, and we use small C extensions for things that need to be fast. Being able to link with C code is hugely important for us, and I don't know if .NET/Xamarin would allow that..?
Getting Python to run on a POSIX environment is actually pretty trivial. Windows RT is harder, which is one reason we've never bothered with a Windows RT port. And on iOS you are limited to using a single core under Python, because you aren't allowed by the O/S to fork.
The biggest pain I've had with Python is memory management: it's almost impossible not to leak memory in a Python program because the garbage collector is quite primitive and reference counting is just so error prone. For an email app you need to be able to run for days/weeks without crashing or blowing up memory usage; you can't just restart the process every 3am like you can server-side.
That's one reason Rust is appealing: memory management is helped by the type system.
- ghuntley 11y agoRe: invoking C/C++ from .NET https://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).aspx https://msdn.microsoft.com/en-us/library/aa288468(v=vs.71).a...
- mwcampbell 11y agoI seriously doubt that using Python bytecode rather than native code makes the application more lightweight. Here are the problems I see: 1. Code size: Bytecode instructions may be more compact than their native code counterparts, since the bytecode instructions are dealing with higher-level abstractions. But the dynamism of Python prevents some major optimizations. First, the bytecode has to include identifiers, since everything is late-bound. More importantly, a packaged Python application tends to include a lot of dead code, because the packaging tool can't accurately tell what modules, let alone individual functions, are actually used. And that's assuming you're using something like py2exe which at least tries to prune the set of distributed modules. 2. Startup time: Of course, even native code can vary here. If you have an executable that's statically linked except for OS libraries, the OS can just read that executable into memory and jump to the entry pooint; that's fast even for a cold start. But if your application consists of an executable plus several DLLs or shared libraries, the OS has to do a lot more work to get it loaded. Python modules tend to be more fine-grained than typical DLLs, and for each module, the interpreter has to find it on the search path, then open the file and read it. 3. Memory footprint: Native code is mapped into memory as shared read-only pages. The OS doesn't actually have to add any of those pages to the working set until they're executed, and it can page them out at any time without having to write to a swap file, which mobile platforms don't have. A few bytecode interpreters, most notably Dalvik, have managed to exploit this, but not Python. So all the Python bytecode has to be in memory all of the time. This is exacerbated by the limited ability to trim the code size as described above. More generally, my thinking on performance, especially perceived performance, in end-user applications has been heavily influenced by this blog post: http://chadaustin.me/2009/02/logic-vs-array-processing/ http://chadaustin.me/2009/02/logic-vs-array-processing/ Here's the money quote: > With disk and memory speeds improving so much more slowly than CPU speeds, the difference between a snappy desktop application and a sluggish application is a handful of page faults. When choosing a technology platform for a project, it’s worth considering the impact to overall responsiveness down the road. And I’m pretty sure I just recommended writing your entire application in C++, which sounds insane, even to me. I’ll leave it at that. That post was several years old. These days I'd expect him to recommend Rust over C++. Of course, you've been developing software for a long time, and you've actually used Python in a mobile app; I haven't. So maybe the issues I've raised just don't matter. I'm particularly curious if startup time has been an issue for Inky at all, especially on the mobile platforms.
- dmbaggett 11y agoHard to say, really. Of course if you write something entirely in C or assembly language, you can make it really compact. In the article you cited, for example, Chad Austin mentions GOAL, which was what we used for the Crash Bandicoot games. That worked well because it was domain-specific and because the rest of the code was all highly-optimized C and hand-coded assembly (the latter mostly by me, in fact). And it allowed us to pack the (tiny) code for the critters in data pages that were very, very precious (the PS1 only had 2MB of RAM). However, x86 assembly, at least, is pretty big, and -- as you point out -- Python instructions are quite high level so you need far fewer of them to do anything. In practice, .pyo files really are generally pretty compact. I'm not sure how it compares to ARM, which has a less crazy instruction set. But I'm very skeptical on the code size claims. It "feels" like Python code is much smaller, but that said I haven't done a real experiment. Regarding startup times, you do have to be careful about imports and regexes: it's easy to write code where importing a module results in a ton of additional imports you don't really need yet, and regex compiles that are better deferred. But in any case, the big driver of startup times now isn't Python -- it's paging in and decrypting the database pages required to construct the first inbox view. That's all done by SQLite, so Python's largely irrelevant to the startup time these days. I'm not sure how things come down with respect to memory footprint, but we fit comfortably even on a lowly iPhone 4, so I think it's becoming less of a practical issue. The huge win for me personally using Python has been that it is extremely easy to come back to code I wrote several years ago (or that someone else wrote) and immediately understand it. For such a nasty domain as email, this really helps a lot. Anecdotally, I've been coding in C dialects since 1979 and I still haven't got the same ability to understand old C code as I do old Python code. For context, virtually all the code I wrote at ITA was C and C++, and Inky is the first "real" thing I've used Python for. It really is a nice language, despite having (in CPython, at least) some frustrating warts (and the whole Py2 vs Py3 issue). Finally, it's worth pointing out that we do use C for the most heavyweight things (embedded database, TLS/crypto, parsing, image format conversion, etc.) So we're probably not typical of either a C or a Python app, really.
- mwcampbell 11y agoFWIW, you've been coding in C dialects since just before I was born. So your experience and judgment have a lot of weight for me. Thanks for taking the time to discuss these things. It's typical for Python applications to depend on C libraries for databases, crypto/TLS, and image format conversion. For parsing, it depends; lxml is popular for XML and HTML parsing, but I don't know of any off-the-shelf equivalent for RFC 822 and MIME.