At 02:34 AM 4/1/2002 +0200, Andreas Raab wrote:
David,
My one reservation is the threads. ...
I wonder why - have you ever looked at Squeaks threads?! Here are few comments on your suggestions.
Not really. I read the Squeak list partly because I am not completely happy with Java, and I wonder what might be better. (All programming languages suck, but some of them suck a little less.) I also read it because I have never been happy with any of the UI programming stuff that I've tried to use. But, I don't have the time to really dive in and go after it. I keep hoping I will have the opportunity. I've tried a couple of times, and gotten pissed off at what looks to me like an unnecessarily terse and cryptic UI (but that is another matter).
But, I do read, and keep track of what things get mentioned over time, and I've noticed comments going by that seem to imply that they are like "green threads" in Java, meaning that I/Os sometimes hang them up, that sort of thing. That's not something I want in a thread system. I also left one item off the list, which is that it's nice if the threads actually use multiple processors on a multiple processor machine. Remember, this is in the context of grumbling at Apple for going with Java instead of Squeak, and Java's support for threads, though not perfect, is not terrible. Apple builds multiprocessors, and I've been using an MP PC for the last five years.
(but, see below).
In Squeak, locks are almost as fast as that. I once measured the overhead of a thread switch (which is what really counts here since if the lock can be aquired the entire operation is basically zero cost)
This says (to me) that you're not using more than one processor. That's going to count against Squeak in some cases. Multiprocessor sync, even when things go well, requires some global knowledge, and that's costly (something like 10 memory bus cycles on a Pentium, was the figure I saw once).
Except, you know what -- I'll bet you've got code written already that assumes that locks are very cheap, and that would change if you went to a "proper" MP-using implementation. I think Java had to deal with this -- early Java was interpreted, and for a while used only simple "green" threads, and all the useful datastructures (StringBuffer, Hashtable, Vector) were synchronized on every operation. That got noticeably painful and slow when things had to work on an MP, and lo-and-behold, unsynchronized versions of Vector and Hashmap appeared. It's now one of the standard Java performance gotchas -- "oh, you used the synchronized data structures when you didn't need to, and it was slow". Is that something you want for Squeak?
So, I don't really know the right answer here, but you might want to think about this one thing carefully before you take the MP plunge. Maybe you don't want to do it -- truly concurrent programming is noticeably harder than the sequential kind, even when sequential programming is simulating concurrent programming.
- there needs to be a consistent/complete set of primitives.
What does 'complete' mean in this context?
Complete, meaning that you can actually build the things you need if they aren't there. E.g., sync/wait/notify lets you build "condition variables" w/o busy waiting, in the idiom of
sync (foo) { while (! condition) { foo.wait(); }}
and
sync (foo) { modify condition; foo.notify(); }
Readers and writers you would build out of s/w/n, but it's tricky enough that I'd fear a goof just typing it out as fast as I can type, and r/w CAN go quickly (even on a MP) if it is supported as a primitive, otherwise it's a pile of bus-locks and not so quick.
"Complete", of course, is not necessarily useful. You can compute anything you want with the S-K combinators because they're complete, but generally, people don't try to get much done with them, because it is so tedious.
So, what you want is a set of operations that is complete (in case you need to build something new) but also contains canned solutions to the 90-95% of the cases that people use synchronization for (buffers, readers and writers, thread pools, shared caches). It shouldn't be hard, maybe you've done it already, plus you can turn those operations into primitives to make them go fast.
David Chase