There must be a good case to be made about light, responsive software. From the other posters here, I take it there's no light alternative to Thunderbird, and I'll keep using it, but 300 MB of RAM for an email client is a bit ridiculous.
There must be a good case to be made about light, responsive software. From the other posters here, I take it there's no light alternative to Thunderbird, and I'll keep using it, but 300 MB of RAM for an email client is a bit ridiculous.
At the risk of stating the obvious, a computer feels snappy when it responds to user actions (clicks, keypresses) quickly. That is a holistic problem -- one that concerns all parts of the system -- so it's hard to optimize. Software tends to evolve "within the lines"; it's hard to make changes that cross abstraction boundaries. But that's where performance is.
On the other hand, hardware has gotten faster unevenly. Disk seeks are the slowest thing your computer does besides WAN access, but those haven't sped up much over the last decade. Disk throughput (and size) have increased orders of magnitude faster than seek time.
But we're still using the same software abstractions (and the same software!) for these radically different machines. For example, stat() is still a synchronous call. In the old days it wasn't all that slow relative to CPU operations. Now it can take 30ms, which is 30,000,000 cycles on a 1 Ghz CPU. So arguably the default should be async.
C is another abstraction that had a reasonable performance model when it was invented, but no longer does. It's hard for the average developer to have a decent (portable) model of a CPU these days, especially with regard to concurrency.
It's a particularly important trade-off as you start considering, for example, more complex layouts where the size and positioning of one element may affect any number of others, elements get added or removed, etc. There's a spectrum of variations between these two extremes that let you choose between maintainable and fast, but neither end really has an ideal combination of both. Language and coding style changes can help, too, but a truly complete solution still seems absent.
The initial load is the second major source of peril for responsiveness. Even if a custom cache for the load is used, the user's first-run impression is still going to be of an uncached experience. Here the disk seek, as you mention, is of huge importance. But I find that I'm personally less irritated by load times than I am by software with intermittent spikes of high CPU usage, which will slow down the whole system at unexpected moments.
One of the other responses nailed what is a more common problem IME -- network activity and UI activity on the same single-threaded event loop. Firefox and Chrome both have this problem (or what amounts to it essentially). For example, in Chrome:
http://code.google.com/p/chromium/issues/detail?id=113389
This bug has gone unfixed for YEARS (older ones were marked dupes of later ones).
The way we write software now is just too difficult to get right. Once you have 1M lines of C++ code there are going to be crazy performance bugs that nobody can fix. Chrome has some of the best engineers on the planet and they're not immune to this by any means.
I guess I would amend my original answer to say that "software size" is the problem. Everybody thinks they know how to write performant software. But that's only when you can fit everything in your head.
I would say that "toss and rebuild" isn't the #1 culprit because the web browser is the ultimate "toss and rebuild" architecture -- that is, every request and response stand alone. Yes web pages can be ungodly slow and unresponsive. But it's possible to make them responsive if you really simplify -- i.e. Google or craigslist.
In theory we could have a stateful web and make it faster. But I think our collective programming skill and our languages/tools just aren't up to the task. I think the web exists as it is, and is as popular as it is, because lots of people with "domain knowledge" could write dirty PHP scripts and such. They aren't fast but they get the job that users want done.
Firstly, architectures today tend to be multitasking and event-driven. A modern GUI application is usually built around an “event loop” that waits for various interesting things to happen, such as the user pushing a key or clicking a mouse, reaching a certain time, or receiving a signal from an external device. When an event of interest takes place, the relevant part of the loop will detect it next time around, and then run the relevant code to react.
However, if that code takes a significant amount of time to run, then the event loop won’t have a chance to react to anything else that is going on until the last event is dealt with. The catch is that things like repainting your application window because the user happened to move another window over the top of it are also handled by the event loop, so if you’ve got an application that is trying to check for new mail every five minutes but your network connection has dropped and it takes 30 seconds to time out, the application might be completely unresponsive to any other kind of user interaction during that time, and might not even redraw properly if you move other windows over it.
The usual solution to this problem is to introduce a degree of concurrency, so that any event-handling code that isn’t guaranteed to complete very quickly is executed in a new thread in parallel with the event loop. The loop itself is therefore immediately free to continue responding to other events, possibly kicking off still more new threads, as necessary. Unfortunately, there are significant overheads to coding this way, so a lot of simple applications don’t bother and just accept that they might become unresponsive now and then. And of course it’s always possible to make a mistake in the design, responding to a certain type of event that is usually dealt with quickly in the main thread without realising that under some circumstances it will take much longer.
The second factor is abstraction. We used to program pretty close to the metal, because you couldn’t get acceptable performance any other way. Today, we build on top of OS kernels, hardware abstraction layers, device drivers, virtual machines, run-time libraries, and who knows how many other tools, all stacked up and each composed of many layers themselves. The benefits of this approach are many: faster development time, more effective testing and more robust software, ease of porting software to run on different hardware or operating systems, and so on.
The downside is that every time you introduce another abstraction, you are potentially introducing an overhead, and those effects multiply. Even if your abstraction is say 90% efficient compared to programming directly to whatever lies beneath it, if you’ve got 10 layers of abstraction between the code you’re writing in your end user application and the hardware you’re ultimately talking to, the effect is to reduce performance by about 2/3. And there are a lot more than 10 layers between your average end user code and the hardware on most systems today, and some of them are far from 90% efficient.
The third and final factor is somewhat related: if development time (or, if you prefer, time to market) is more of a priority than raw performance, it’s easy to skip over the kind of optimization work that used to be essential to produce software that ran acceptably quickly and within the relatively limited RAM and permanent storage capacity available. It’s one thing to skip the fine details and hand-tweaked assembly language, which was often a very expensive activity in terms of time spent vs. resulting speed-up. It’s another thing to just throw in the first data structure or algorithm that comes to mind, often because whatever software development toolkit you’re using has a limited set of options available and maybe it’s not worth the time to code up something more appropriate, or maybe because as the industry has grown a lot of developers aren’t either formally trained or keen hobbyist geeks any more and not everyone knows about all the options. This is how you wind up with abstractions that are a lot worse than 90%, or that don’t scale well as the amount of data they have to deal with increases and assumptions that the hardware is “fast enough to make up for it these days” break down.
So, in summary, and in more of a cause-to-effect order:
1. The emphasis on reducing development time because of commercial pressures or other non-technical factors, combined with a certain complacency about the capabilities of modern hardware, means that not as much optimization tends to be done before code ships today. Sometimes this introduces a modest overhead, but it can be severe if a poor choice leads to scalability problems.
2. Even if the overheads of any one function are modest, we build modern systems from a stack of many abstraction layers, and their overheads multiply. The compound effect can easily be the equivalent of running on hardware from several years ago, even if no individual layer was grossly wasteful.
3. Because we tend to use event-driven architectures for a lot of modern software, including most GUIs, a single slow operation can block the whole event loop and effectively make the whole UI unresponsive indefinitely. More advanced architectures that would prevent this have significant development costs and aren’t always used for the same reasons as above.
[Edit: OK, this is getting a few upvotes and no-one’s replied suggested cutting it down, so I’ll leave the whole post as it is. Sorry if anyone does feel it’s too long.]
At least, in Windows, explorer is pretty much instant.
$20? $50?
What operating systems? Is there anything specific features/aspects/licensing that would push you to $50?
If neither, (I assume free or close to it) why? How much time do you spend in an email interface? How much is your time worth?
Cheers!
The thing is, however, $100 paid to closed-source software vendor never guarantees he won't be out of business or bought by some Novell that will promptly run it into ground in a year or two. With open source chances for product survival are higher - though, as we see here, are in no way guaranteed.
Just in case anybody cares, I'm currently on Mac OS X, but when I worked on Linux & Windows, I used Thunderbird too, and the same applies for both of these OSes too.
That would seem to be the catch, I was originally talking about just an email client. This would now be an email client, exchange client, calendar, address book...
These are all things that Thunderbird doesn't get right. Also, search is completely broken.
I've got a tray icon in Gnome Shell (and I had one when I was using Gnome 2), using the FireTray extension, and there is also a Gnome Integration extension that provides a tray icon, in theory, but it doesn't work for me.
All of this can be solved by installing addons.
What is a tray icon? Is that a windows thing?
PS: What is the signifigance of the italicized is?
The "is" was just emphasis.
Exists in OS X, Windows, (both since their nascent editions) and Gnome since at least 2 if not 1, and KDE since at least version 2 as well.
Usually shoved off to the right as a cluster of icons designed for some core verbiage and notifications.
Edit: I saw you use Ubuntu. I happen to use Ubuntu as well. Does cross-platform matter to you?
Edit2: Got it, cross-platform doesn't matter. Cool, thanks for the responses!
Edit: I'd be happy if the developer of Sublime Text 2 decided to have a go at making a modern, cross-platform email client. Something tells me it would be exactly what I want.
Anyway, I'm starting to get to the point where I don't trust a piece of proprietary software to not try stealing my data, so that's a non-starter for me.
This is not my first tricycle ride around the HN block.