July 14, 2006

Crazy ideas: A possible future for document-based applications...

Tonight I was thinking about global variables (or, their equivalents -- class variables or class methods that return static values), and how gosh-darned handy they are, except for the fact that you don't often use them because what you want is variables that are global to a particular document, and if you have multiple documents open you don't know WHICH particular document unless you have a backpointer to it, in which case it's not a global any more, is it?

And then I realized that, in the future, each instance of an application will have only one document. Which is to say, if the user opens 10 TextEdit documents, she'll actually have 10 instances of TextEdit running.

The advantage to this is that, if you do something that is slow or modal in one TextEdit document, you don't have to, like, go check your mail or do something else -- you can edit another TextEdit document while you wait. When you think about it from a user's point of view, why is it that when TextEdit is hung (doing something really intensive on one document, or even just hanging for the fun of it), you can access Mail or Safari documents, but not other TextEdit documents? Is there some research that shows you are more likely to want to go send a Mail message than edit another text document? This is an app-centric feature in what should be a document-centric world.

But imagine if, say, some crazy web page made Safari crash, but it was that only one window, and all your other Safari windows were still open. Imagine if you hung Preview by saving something as a JPEG2000 while playing a movie (true story) and you could just kill off that document and all your other images you were working with were still around?

So, how would this work? Well, at a lowest level (the OS), it's pretty simple. Mach already will automatically share pages mapped in from the application's resources and object code, between running instances of the app. (In fact, I believe this sharing of resources happens right now if two users use Fast User Switching and run the same app.) The OS would have to actually launch the application multiple times to create multiple documents, which would mean there'd be an extra memory overhead of a whole application's stack being created (and the objective-c environment being fired up, classes being initialized, etc), and there'd be a speed hit from this as well. However, speed and memory are two things that are getting cheaper, whereas programmer time is not. And startup times are getting faster and faster even without hardware improvements, thanks to cool OS and Cocoa tricks. I certainly don't think those are exhausted (freeze-dried apps, anyone?).

Then, at the Mac workspace (Finder) level, Apple would have to do some work with things like AppleScript and LaunchServices so they are aware that there is no longer just one, say, "TextEdit" to which it can send messages. Some things would work just fine with little reworking -- if you have an AppleScript that says, "Open this document in TextEdit and do blah blah" you already don't know and don't care how many documents TextEdit has open right now, so this change wouldn't matter. But if you look at an AppleScript that says, "Go through TextEdit's open documents and tell the first one..." then that would obviously require some OS glue to work correctly.

On the dock, Apple would only show one icon for any given app, no matter how many instances of it were running. Apple could pretty easily rework the workspace so all documents that were running in the same base application were shown/hidden together, even though they were in different address spaces. The Windows menu wouldn't be hard to modify so that it just brought another app to front, as well, if you selected a different document.

The user wouldn't (necessarily) want inspector windows to move around when she switched documents inside a single application, but that would be easy to handle -- it wouldn't be hard to do some simple messaging between instances of the application telling them all where their "Blah Inspector" should be located and whether it should be hidden, for example. This kind of coordination of the "shared look" of the app would be easily built into AppKit -- you'd simply decide ahead of time what should stay the same between documents (maybe you have a special icon dock that sits at the top and should be there for every document, for instance) and AppKit would make sure that all running instances are in the same state, much as it does right now with toolbars (albeit in a single process, but the extension is not hard). Consider, for instance, the color panel, where swatches are always the same across all running programs, or the font panel, which displays the same fonts and groups no matter the app. This is a solved problem.

The user experience for all this could be just like the current one under OS X, except crashes and hangs and modal operations in a document would be handled MUCH more gracefully, and the task of writing document-based Cocoa programs would get simpler. Imagine, for instance, if you're populating a popup button somewhere with, say, the names of all the objects in a Graffle document. The neat thing would be, you wouldn't need a backpointer! There's only one document, so you can just treat it as a global: "Hey, global document, give me all your object names." You're done. (Sure, you can ask the NSApp for its currently active document right now, but there are instances when you're doing work for a document but you can't be sure that it's the active document -- it could be one of the background ones. This would eliminate that uncertainty.)

Conceptually, this whole model seems a lot cleaner to me, basically because different documents inside an app almost never talk to each other. There's really no reason have them in the same address space, except for the fact that launching apps was expensive (up to now) and took up memory.

But as we switch to these new Intel machines, we're finding app launches are, like, a fraction of a second. And, history has shown us, whenever we have an excess of speed or memory, we use it to make programming simpler for ourselves, which allows us to make cooler programs for users.

Heck, in the old days, we only had one address space, and if you crashed a program your whole machine was S.O.L. Now we can't even imagine such a barbaric time. I think one day we'll look back to the days when a single application had multiple documents and say, "Why? That's such a pain to deal with! What if one document corrupts memory! They'll all get messed up! That's crazy!"

Labels: , ,

56 Comments:

Anonymous mj said...

I remember when Steve said about the future maybe having multiple "Finders" and thinking what he meant was that Finder would act like apache and spawn new "Finder" processes to respond when we requested something and therefore would be less likely to block when it hit a deadlock.

Same theory, just a few years later.

I agree - it's a cool idea and not an unobvious one. Yours is just written better than my pseudo-technobabble.

Spose it's just a hierarchical model again. All processes are daughters of the kernel. This would have application windows/documents being daughters of the main process.

Think beyond this. Imagine being able to use those QUAD machines on non-MP aware photoshop filters or other processes within one application? One filter running per document.

This could make the difference. It could be a leap for Mac OS X the way that Mac OS X was a leap for Mac OS 9 users. I'm wondering about whether you could SHARE processes/documents between different users on the same machine or even across a network.

July 14, 2006 2:36 AM

 
Anonymous telos said...

An increasing number of apps ause tabs. So, for instance, how would this work if one of your Safari _tabs_ crashed. Would you be able to have that single tab close and leave the others intact or would the entire window close down with it?

July 14, 2006 3:26 AM

 
Anonymous Pierre said...

Hello Wil,
Interesting thoughts, but I am not sure to fully understand what is behind.
First, if I remember well, as soon as Windows95 (and certainly Unix for more time), the OS was designed to cache shared libraries or some resources to improve the launching of several instances of an app. However, I have absolutely no idea of how "deep" it is. Are you talking about more advanced sharing ? Your knowledge of OS is certainly better than mine (not quite difficult :-), so, have you got some details to provide about how your idea is different of what can already be done ?
I have the impression that you are just thinking (well) about the points where the OS user interface should be modified, to hide the fact that the application has several instances.
But, in such a structure, how could documents easily share data ? You say that they almost never talk to each other - that's right - but what about, for instance, an history (like in Safari) ?
Another idea : what should a "top" (or activity
monitor) report ? Several instances or just one ? If it reports several instances, how will you identify which instance is linked to which window ? If it reports only one instance, how will you trace a particular instance ?

Regards,

Pierre

July 14, 2006 5:08 AM

 
Blogger Paul Davidson said...

How about improving CoreData to the point where even when an application crashes, its data and state are saved and can be restored?

July 14, 2006 5:33 AM

 
Anonymous Jason said...

It seems like a proper use of threads (say, one per document) would solve all of these same problems today (ok, with the exception of a horrible crash. But who writes apps that crash these days?)

In fact, that one-thread-per-document concept was basically built into BeOS, except it was actually per-window. Each open window effectively automatically had its own event dispatch thread. Well designed libraries made this actually quite easy to program for.

July 14, 2006 5:38 AM

 
Anonymous Anonymous said...

I personally think it would a heck of a lot cleaner if the AppKit was instead modified to better handle threading, in particular designing the whole document-based app set-up to be naturally threaded.

You would have one thread for the app, and then one thread per document. That, to my mind, would work quite nicely. Obviously you also have to make the threading more robust so that a thread can crash without majorly affecting the rest of the app.

And to be honest, in OS X there isn't a huge lot of difference from the OS's point of view between threads and processes.

July 14, 2006 5:45 AM

 
Anonymous Daniel Jalkut said...

I think you're on to something with the "document-centric" approach. Windows does this to some degree of satisfaction (and to another degree of annoyance).

But there are a lot of devils in the details. While there may not be much interplay between documents in most applications, there are a lot of things to keep synced. When a preference changes in one document, what happens in all the others? Separate preferences for every document? That could get confusing.

I suppose if the benefits outweigh the hassles of moving away from our comfortable "all-knowing core" approach to app design, then we'll move in that direction. Otherwise, I don't think there's much chance for this.

July 14, 2006 6:05 AM

 
Anonymous Hrunk said...

Microsoft moved Windows towards this model when it got rid of MDI (Multiple Document Interface) in Office. You can even ask Explorer and IE to open each window in a separate process, but since Windows processes are so heavyweight (compared to UNIX) you get a noticeable performance hit.

The difference in Microsoft's case was that MDI was a usability nightmare.

I can't help but think that rather than trying to fake a document-centric approach with existing apps it would be better to require apps to be re-engineered. Then you could go the extra mile and have individual tabs in Safari running as disparate processes. If the window manager can present several applications as a seamless whole then it should be possible to present views from multiple processes as a single window. i.e., an NSView doesn't usually care where it's drawing.

Maybe in OS XI, when the OS is based on a new kernel, Windows apps run natively and people still buy junk Windows laptops because they're cheap and I have to remove all the malware. Sigh.

July 14, 2006 6:23 AM

 
Anonymous Anonymous said...

i think it is a good suggestion.

my app is already a single-document app, but it turns out that to support converting from several old and "foreign" doc formats to a current doc format, it's easiest to create different doc classes. so now i can't do global vars again. some of those cocoa doc objects hang around longer than you would expect.

July 14, 2006 6:43 AM

 
Anonymous Anonymous said...

I believe Taligent (http://en.wikipedia.org/wiki/Taligent) is what you are calling for. It was a document-centric OS.

All very impressive technology that was unfortunately C++-based and probably controlled more by corporate politics than a desire to ship.

Working at IBM during this time I saw several impressive demos and even demoed NeXTSTEP to a few people that we somehow involved with the project.

July 14, 2006 7:04 AM

 
Anonymous Anonymous said...

Another note on Taligent.

Being document-centric, from what I could tell, you didn't really develop applications, you developed documents and shared services / tools to manipulate those documents. Kind of like Mac OS X 'Services' with tighter integration to the OS.

Also, I seem to remember that it used similar concepts to OpenDoc in that documents could be embedded in other documents.

In addition I also seem to remember that there was the ability to have 'live' documents, in that they were always active and the state was always saved, you didn't have to start an application to use them.

July 14, 2006 7:16 AM

 
Anonymous Olly said...

I like it.

MS Ofice on Windows already gives the impression it's doing that, in that each document gets its own taskbar entry, it's own window and so on. Whether or not it's separate iterations of Word (et al) underneath I don't know.

July 14, 2006 7:26 AM

 
Blogger louis said...

While this is conceptually appealling, and certainly the sort of thing one might want to consider when designing a new system, it is very difficult to retrofit onto an existing one in any sort of reasonable way.

I think you would be surprised just how much implicit state, memory, and consumed processor cycles are tied up in most launched applications. If you want you can find out, go into Terminal, go into the app bundles, and manually launch the app binary (not with open, run the binary from the commandline). That will allow you to launch mutliple copies of the same app. I suspect the memory footprint of 2 textedits with 1 document each is substantially larger than one instance with 2 documents. I also suspect for more coomplicated apps (like Safari) the memory footprint increases very quickly.

It is easy to say ram and CPU are getting cheap, and you can ignore it, but that misses the key point. The average software stack is already constrained by the ram and cpu on consumer level systems. Yes ram will go up, but the ram increases on stock machines still give palpable, quantative performance differences. The ram is not being wasted as is.

I actually decided to check real quick, here is the output lines from top of me openning 3 TextEdits. The first has 2 documents open, the next 2 each have one of the documents.

$ cd /Applications/TextEdit.app/Contents/MacOS/
$ ./TextEdit & ./TextEdit & ./TextEdit &

::Opens appropriate documents in appropriate TextEdits::

./top

PID COMMAND %CPU TIME #TH #PRTS #MREGS RPRVT RSHRD RSIZE VSIZE
17681 TextEdit 0.0% 0:00.94 4 106 178 3.57M 12.9M 10.2M 378M
17679 TextEdit 0.0% 0:00.61 4 102 171 3.30M 11.6M 8.98M 376M
17676 TextEdit 0.0% 0:00.79 4 104 176 3.43M 12.3M 9.96M 374M


As we can see, the RPRV for each is ~3.5 MB RSIZE for each is about 10MB. So the memory memory footprint increased ~30% in the 2 document case, and if we extend this out ~60% in the 3 document case. Now I don't usually have tons of TextEdit windows open, but I often have 30 webpages between windows and tabs. Assuming it is the same, (and I suspect it would be worse, but don't feel like checking since that is a lot harder to control being networked and all) then we would be looking at .3*29 -> 870% increase in Safari's footprint.

Even assuming you end up with enough ram, interfaces in general do not keep up with Moore's law. We were at 6.4 GB/s to ram when the G5 came out, and we are at 10.6 GB/s today, a 66% increase in 3 years. FB DIMMs style memory interfaces do provide a one time sudden bandwidth boost to ram, but only for people who want to use more than 2 ram sockets. So not only am I using more ram, but I need to read and write a lot more ram, which starts to cost a lot. You can't just cache it, because they are in fact distinct extra bits.

Anyway, just my 2 cents as someone has done a bit of perf work over the years.

July 14, 2006 7:36 AM

 
Anonymous Torsten Kammer said...

I wonder whether this is really the best possible approach to solve this problem. Of course, there is hardly any need for documents to interact, so removing that would not be much of a problem. However, especially on Macs, there is always the implied concept of a single root application instance running, which manages the menu bar, utility windows, preferences, script commands and so on. This with all the inter-application communication required seems to be doing hard work to emulate the current principle, and I do not think that this is really a clean solution. Something hierarchical, with the documents being some kind of sub-apps that communicate with a single master application might be more practical. It would, of course, be useful if the document-apps can survive a crash of the master application, but with all the menu bars and panels I don't know if that is really practically possible.

July 14, 2006 8:13 AM

 
Anonymous Coty Rosenblath said...

Interesting idea, Wll. As it is, I often do this implicitly in my browsing by keeping different browsers (Safari, Camino, Firefox, etc.) open and using one for my more speculative work, another for plain old surfing, etc. (I could do multiple instances on one, and that would be more memory efficient, but there are other benefits to having a few open.)

I think Paul is on to another option, too, in simply make apps more resilient in the face of the inevitable crash.

July 14, 2006 8:21 AM

 
Anonymous Anonymous said...

Guys, this is less about the interface and more about the technology. He even goes out of his way to explain how the technology could happen without a change in UI.

Pretty clever. It's getting us some advantages of threading but without the annoyance of threads, and then gives us additional benefits. All at the expense of RAM.

Given that we're more likely to have 4GB or 8GB of RAM in our machines (and 2 or more processor cores) before we're all running on 10k RPM hard drives, this sort of solution does make sense.

July 14, 2006 8:52 AM

 
Anonymous Edward O'Connor said...

"Tonight I was thinking about global variables[...] and how gosh-darned handy they are, except for the fact that you don't often use them because what you want is variables that are global to a particular document, and if you have multiple documents open you don't know WHICH particular document unless you have a backpointer to it, in which case it's not a global any more, is it?"

Sounds like buffer local variables to me.

July 14, 2006 8:53 AM

 
Anonymous l├Žng said...

I just hope there are enough Apple developers reading this blog. I think, it's a great idea.

July 14, 2006 9:10 AM

 
Anonymous Anonymous said...

This seems like ranting from someone that doesn't know how to keep document state properly.

July 14, 2006 9:45 AM

 
Anonymous Jeff Atwood said...

> And then I realized that, in the future, each instance of an application will have only one document. Which is to say, if the user opens 10 TextEdit documents, she'll actually have 10 instances of TextEdit running.

Wow, the future sounds an awful lot like Windows today.

Did you mean this in an ironic way, or something? Or did you just give Windows a compliment?

July 14, 2006 10:01 AM

 
Blogger Carl Johnson said...

This is completely off topic, but I think you're an influential guy, so I'll mention this idea of mine you reminded me of:

Permissions by user is a dumb idea.
Permissions by application is a smart idea.

Think about it, why should RandomUntrusted.app that I downloaded off the web be allowed to open and erase ~/Documents, ~/Music, ~/Pictures, etc.? All that it needs to access is ~/Library/Preferences/randomapp.plist and maybe Application Support. Everything else, it should have to come begging to me for permission.

I already filed this one with Apple's bug reporter long ago, but I think some advocacy from someone well respected like you would be helpful.

July 14, 2006 10:04 AM

 
Anonymous Anonymous said...

From the perspective of the OS developers and the users I think it would be better for document based apps to have each document in it's own thread and to be able to tolerate the threads' crashing or hanging.

That design seems cleaner to me from the developers perspective and for the user, I think it presents less opportunity for inconsistent behavior when the app developer decides to be lazy about making sure all the separate processes sync up correctly.

July 14, 2006 10:04 AM

 
Blogger William Henderson said...

I think there are two basic possibilities when it comes to the way a user thinks of an app (and therefor wants it to function):
1. Each document in an application is an entirely different task, as seperate as writing a book and writing a letter.
2. Each document in an application is intricately related, and they all need to be tied together.
Now in the first condition, what you've layed out sounds like a really kick ass plan, and I even propose to take it one step further - why should you 'hide' the way the app is actually working from the user? You've just made the decision that the user is interested in treating the documents as seperate tasks. Why should they be together? Sure, you could come up with some creative way to organize the tasks (say, by application, but its debatable whether that's the best way) so that it was easier to manage when there were a lot of them, but this is not the same as the current set up. To me, I think it would make the most sense to organize document-tasks by how they are related (so what application they are could be irrelevant) and let each document-instance have its own representation. Think of a dock where you can drag arround document-tasks, stack related tasks, etc.
Now in the SECOND instance, I'm not so sure. Safari is a great example, because webpages are, like, hypertextual, so its really, really likely that the webpages open in seperate documents are going to be highly related for the user. Document-seperation (at least at the user-level) would be a bad thing. Now just to throw it out there, maybe what this really means is that those seperate tabs have no business being a document. I mean you look at a really advanced web-browser like DevonAgent, and its clear that one window is one document, one research-project, as far as the user is concerned. Actually, Apple could do NOTHING for this instance, just leave it the way it is and work on the other case where documents are seperate, and just rename one or the other (so, for example, working on an old-world document-based application would be called working with 'subtasks' or something). Because multitasking is hierarchical. Or, if they really wanted to go to town they could actually IMPROVE this area too by making the document-metaphor LESS prevelant and doing more to relate the 'subtasks'. Tabbed-browsing is a good example of this. I saw a hierarchical-visual called TrailBlazer that was another good example.
BUT BUT BUT you say, what if there are applications that can be used either way. Well, I might say that if this is the case one or the other user is missusing the app, but that sounds REALLY wrong doesn't it? We don't want to say that Grandma is wrong for keeping one webpage open per window or that a student doesn't want his english report and the notes to it treated as connected, do we? Well I see no problem here. Apple would have to rework the metaphor a bit, but in the end I think it would make more sense.
Think of the new stack-friendly Dock. To open a new document (as in instance of an application) the user drags the application to a blank space in the dock to create a new 'task'. To organize tasks, the user stacks them and makes them 'subtasks'. The OS could be smart enough to make relations between tasks, and Safari's developers could stop think about documents as seperate and everybody else could stop worrying about connections between documents. Eh? I think a good mockup is in order...
one of these days...

July 14, 2006 10:08 AM

 
Anonymous e said...

You could avoid the start-up costs of initialization, and ongoing costs of having multiple copies of the program text lying around. By..... FORKING!

I think.

If you initialize once, then your program text is properly set up in memory. If you fork off each subsequent instance of the app, your OS should do lazy copying of the program state, meaning that the fork time should be fast. Individual pages will only be copied when they are written to.

July 14, 2006 11:18 AM

 
Anonymous Anonymous said...

very good idea. could create new distributed issues but the crash protection alone is worth it imo.

July 14, 2006 11:21 AM

 
Anonymous Mark Stultz said...

actually, we're all going to be moving to OpenDoc soon.

July 14, 2006 11:26 AM

 
Anonymous Anonymous said...

I think Jason said it first, that this is more a threading issue.

Your suggestion, while interesting, brings to mind the less appealing aspects of Windows. One of them is using IE, where closing the last window causes IE to quit, and I have to wait for it to re-launch when I'm trying open a new page AND I'm forced to manually re-launch IE in order to open that new page because there's no app running that will take my keyboard shortcut or give me any other way to open a new page easily.

I think the paradigm shift would be too great, and you'd have too many Mac users saying to themselves WTF, I have to relaunch to open a new document? This is why I switched FROM windows.

July 14, 2006 11:31 AM

 
Blogger louis said...

Just for reference, you cannot avoid program startup costs by forking, because you cannot fork a GUI app on Mac OS X. This is because mach_ports have a unique relationship with the process, and cannot be inherited by the child. Yes it is not consistent with unix semantics, but it does not effect things that use purely POSIX APIs.

Also, you don't have extra copies of the text as it is, unless you had to override libraries or something. All the numbers I listed in my first post are purely instance costs associated with TextEdit, no app text or anything like that.

July 14, 2006 11:47 AM

 
Anonymous Anonymous said...

I don't like this idea.

Today, at work where I am forced against my will to use Windows, I opened the same text file twice in Notepad. Saving changes is so confused that it is appalling that there is not even a warning that you may not be getting what you expect.

I have always preferred The Apple Way of having a single instance of the app managing the multiple docs. My answer to those who have zillions of docs open living in fear of crashes: save often!

July 14, 2006 3:19 PM

 
Blogger English Writer said...

Here's a *really* crazy idea.

How about fixing Delicious library so that you can install/upgrade it as a non-admin user?

That would be way better than 100 blog posts ...

July 14, 2006 4:03 PM

 
Blogger Ryos said...

Protected memory for documents! Interesting idea. Except, if the object resources etc. are being shared among instances of an app, isn't it still possible for one instance to crapp all over the other's memory and hose the whole system? That would make sense to me, but I'm not a Cocoa programmer. Caveat ignoramuser or something.

July 14, 2006 4:15 PM

 
Blogger Wil Shipley said...

English Writer: I agree that it'd be nicer if Delicious Library popped up a prompt to allow you to override permissions on your /Applications folder if you're not an admin, but, honestly, in the meantime you can, say, just install the application in your personal applications folder (~/Applications) and it'll install/upgrade fine.

I don't think it's unreasonable for non-admin users to have a program NOT automatically write into a shared directory. I mean, that's the whole point of not being admin. But, again, I agree it'd be nice if we wrote an override -- but remember, every feature we add is another feature we don't add, or a slip on the release date.

July 14, 2006 4:20 PM

 
Anonymous Anonymous said...

Carl,

What you've described is what's called a capability architecture, where permissions to an object are bundled together with any reference to that object. Google for "KeyKOS" and "Coyotos", and you'll be able to find the academic literature on the subject from there. You particularly want to read the paper on the "confused deputy problem".

-jcr

July 14, 2006 5:11 PM

 
Blogger English Writer said...

I don't think it's unreasonable for non-admin users to have a program NOT automatically write into a shared directory. I mean, that's the whole point of not being admin. But, again, I agree it'd be nice if we wrote an override -- but remember, every feature we add is another feature we don't add, or a slip on the release date.

--

well, I'd argue that the current behavior, which seems to be
- show a dialog box that some directory cannot be renamed, and then corrupt the current binary is probably broken no matter what.

What I'd hope would happen is that I'd be prompted for an admin username and password like other software does.

I thought one of the strengths of OS/X was you did not need to be always logged in as admin.

However, do not fear, you're in good company as apparently Adobe hasn't figured this out yet. Their S/w just installs and then fails to run.

Amazingly they dont consider it a bug.

July 14, 2006 5:12 PM

 
Anonymous Anonymous said...

Congratulations, you're reinventing the way UNIX user interfaces have worked for years: separate application instances for separate documents, which indeed simplifies both the user interface and makes things more robust.

It's funny to see how both Apple and Microsoft are reinventing the wheel years too late and then those companies are claiming that they're actually innovating.

July 14, 2006 6:57 PM

 
Blogger Wil Shipley said...

It's funny to see how both Apple and Microsoft are reinventing the wheel years too late and then those companies are claiming that they're actually innovating.

Ok, no need to be rude. I don't think it's ever "too late" to improve a system, I don't work for Apple, and I never claimed I was innovating, I was just bandying about an idea for discussion.

I've been programming for UNIX for 22 years now: don't need a lesson in it.

July 14, 2006 8:05 PM

 
Blogger Abhi Beckert said...

I actually have an as-yet unreleased v2.0 update to one of my apps that follows your idea almost to the letter. It's a replacement utility for System Preferences which provides a better UI to the installed panes by, among other things, loading a separate, dynamically created application for each preference pane you open.

It works really freaking well in practice. "Documents" open extremely fast even on an 800Mhz G4 and it's even acceptable on a 350Mhz G3 iMac. In my app the overhead is almost non-existant. Mind you, some of the system pref bundles take a while to load, but that's the same as if you open a ~600MB jpg, doesn't matter what document architecture you use, it won't happen instantly.

While my app is small and complex ones would be slower, I'm pretty sure you're overestimating the performance hit. Without any OS-level optimizations on top of what we have now, I doubt you'll need an intel mac, or even a G5, for excellent performance.

The only real difference between your theory and my application is that I have a completely separate *.app bundle and dock icon for each document (which works well for preference panes, it was like that in OS 9, and it's a better system for users who make regular trips to system prefs). Obviously, I'm sacrificing some performance, but with my simple app it's perfectly fine even on a slow mac.

July 15, 2006 3:44 AM

 
Anonymous Anonymous said...

Try to think outside the document-box for a second. Documents are not always completely independent objects and in some cases you often want to do computations that involve data from many open documents.

Massive amounts of nontrivially-structured data in the case of, say, an audio editing application.

So you would have eliminated the need for back pointers, in exchange for doing *lots* of complex IPC...

The ease-of-programming argument doesn't hold up.

July 16, 2006 5:38 AM

 
Anonymous Anonymous said...

The biggest question this idea raises for me is when it comes to scriptability. If you want to send a request to FooGraph, and each document is a separate app, which instance do you get?

-jcr

July 16, 2006 4:17 PM

 
Anonymous David Glasser said...

I noticed that Parallels Desktop seems to do that -- its "New Window" menu option appears to fork a new copy (two icons show up in Command-Tab, etc). This of course makes sense -- running two VMs in the same process seems a little nuts.

July 17, 2006 1:21 AM

 
Anonymous Anonymous said...

Eeeerm, we have multi-threading since .. like .. many years? Why not use it?

July 17, 2006 2:27 AM

 
Blogger Wil Shipley said...

Eeeerm, we have multi-threading since .. like .. many years? Why not use it?

This is actually a valid question. The answer is, I'm not that smart. I'm not sure if I've met anyone who is, frankly.

I designed and co-implemented one of the few massively-multi-threaded applications under Mac OS X, which is the OmniWeb browser.

It was hard. HARD. REALLY HARD. Not hard, like, cool hard. Hard, like, stupid annoying unreproducible bugs and crashers and deadlocks hard. Hard like, the code was hard to write and hard to read and hard to modify.

It wasn't fun. I frankly regretted it.

I'm not the only person who has (mostly) sworn off threads. Pretty much everyone I know who's used them now agrees that the less you mess with threads, the more stable your program's going to be.

Exceptions? Of course. If you're doing I/O, threads can be dandy, especially I/O across networks. And if you've got a chunk of heavy computing you need to do and don't want to bog down the UI, and the computing doesn't require anything from the user as it runs, well, thread away, hombre!

But there's a good reason most applications aren't threaded. It's because it's TOO FREAKING HARD. It's at the limit of what human brains can handle.

If you find thread programming easy, you're either much, much smarter than I am (and congratulations), or you're ignoring a ton of horrible things that can go wrong, and when you scale your app up and/or try to deploy you are going to get bit in the ass so hard you'll think you'll sit lopsided for a year.

July 17, 2006 2:44 AM

 
Anonymous Damien Sorresso said...

This solution seems like it'd be a pain in the ass for authorization and authentication. If you had an application that needed to perform an administrator task, each instance of that application would require its own authorization reference. (I don't know about you, but I'd be weary of passing an authorization reference to something that wasn't a helper tool.)

Also, this approach would make factoring code kind of a pain. If an application has a helper tool, does the helper tool get shared among all instances? Or does each program launch its own helper tool, requiring multiple authentications? You'd end up having a lot more root-level code running at once. And more code running with those privileges is always a security risk, even if it's the same code.

Also Wil, wouldn't this kind of system system make frameworks an ideal solution for compartmentalizing code? The more functionality you could put into a framework, the better, since all instances of your application could link against that single copy of the framework in memory. Oooh the irony. :D

July 17, 2006 9:03 AM

 
Anonymous Morgan Aldridge said...

As Jason mentioned, exactly this functionality was designed into the BeOS. And I don't think anyone can exactly say that the BeOS was slow or a heavy OS. Betcha wish Apple had bought BeOS instead of NeXT, right?! ... Actually, I still much prefer Obj-C over C++ as I'm sure many of you do.

Although MT (multi-threading) seems like the obvious solution and it is a valid alternative, as Wil says:

It [is] hard. HARD. REALLY HARD. Not hard, like, cool hard. Hard, like, stupid annoying unreproducible bugs and crashers and deadlocks hard. Hard like, the code was hard to write and hard to read and hard to modify.

There's a reason that unix does applications (er... processes) like this already, it's easy. If you're already writing your programs this way, you quickly learn when to balance forking off a whole sub-process (a document, for example) and when you create a thread (maybe that document is a web page and is downloading a bunch of media). This also helps you learn better how to handle IPC because you tend to design your program to minimize the need for IPC (the right tool for the job 'thing').

Unfortunately, the audio editing application example was probably not the best (again, see BeOS). How often do you have a project that pulls audio from another open document and streams it into the mixing/editing of another document? It's usually more of a multi-track and/or multi-instrument kind of thing. (Now, I don't really use Logic or Soundtrack, so I could be wrong, but I think it's less of an issue than text editors, file browsers, web browsers, etc.)

So you can't for GUI apps under OS X? That can probably be fixed or modified. Too much overhead by forking another GUI process for a single document? How much overhead are you saving in code to handle multiple documents, modal sheets per document, etc.? You can probably slim it down quite a bit. I'd wager OpenStep/Cocoa could be modified to support this kind of application programming more easily (and reliably) than supporting full multi-threading of Multiple Document apps.

I know that this kind of solution would have saved me many times over when I failed to bookmark that one tab in Safari (which was not even the front-most tab, of course) when another site brought it to it's knees. And probably other apps as well, but that seems to be the one I abuse the most (while waiting for OmniWeb 5.5 to be released).

Regarding the discussion over installing/upgrading Delicious Library if you're not an admin, while a bit of a bother, it's not that big a deal. If you can't work around it in a few seconds (e.g. download the update from the Delicious Monster web site, delete Delicious Library from /Applications, drag the new Delicious Library to applications -- it'll ask you to authenticate as an Administrator -- or just install in ~/Applications) then maybe you should think more about why you have a non-admin account (or why you do).

July 17, 2006 10:54 AM

 
Anonymous Morgan Aldridge said...

Regarding Damien's post about authentication:

How often does one need to authenticate as an admin for multiple documents in an application? Also, authentication is a per-user issue, so once you're authenticated as an admin you retain those privileges for a short period of time. If you were to switch documents, do a bunch of editing, and then try to save to a location that required admin privileges, you'd have to authenticate again anyway, so it shouldn't matter which instance of the application was being authenticated anyway.

I don't think this would break the keychain either as the application will still have the same name and probably the same bundle identifier.

July 17, 2006 11:03 AM

 
Anonymous Bob Peterson said...

For those who have not seen it, the threads-are-hard argument was also presented by Ousterhout here:

http://home.pacbell.net/ouster/threads.pdf

July 17, 2006 12:39 PM

 
Blogger William Henderson said...

Morgan: install Saft and you won't loose tabs when safari crashes.

July 17, 2006 3:46 PM

 
Blogger groovinkim said...

I do this in a non-optimal way right now. Similarly to Cal, I often have different browsers open for different tasks. I do the same thing with text files, often having several different places I'm saving text (stickies, textedit, neooffice, etc.) If I were more organized I'd probably put them into separate virtual desktops.

'Twould be so nice if all applications had a tabbed-browsing type approach, though. I don't know how technically difficult it would be to implement, but even if it was done in a less-than-ideal way, some people will soon enough have enough ram/processing power to handle it..

July 17, 2006 5:07 PM

 
Blogger Wil Shipley said...

Damien opined: Also Wil, wouldn't this kind of system system make frameworks an ideal solution for compartmentalizing code? The more functionality you could put into a framework, the better, since all instances of your application could link against that single copy of the framework in memory. Oooh the irony. :D

No, frameworks would be no better. (Is there double-irony in you calling something ironic when it is, in fact, merely incorrect?)

Mach will already share the resources of the main app, as I said in my original post. Moving code to a framework would have no effect except to make launching each instance a tiny bit slower as it is linked into place.

July 17, 2006 5:15 PM

 
Blogger Abhi Beckert said...

...while waiting for OmniWeb 5.5 to be released

Google for "omniweb 5.5 sneaky peak". The current release is very stable on my system.

July 17, 2006 6:27 PM

 
Anonymous Morgan Aldridge said...

William wrote:
Morgan: install Saft and you won't loose tabs when safari crashes.

I've used Saft in the past and it's now pretty stable, but I just no longer feel the need to hack my apps, especially with Input Manager hacks. :\

Although I agree with Gruber that extensibility is important and that the ability to do so without an official API is great, I'm just not so into it as I used to be.

I will look at it again, though.

Abhi wrote:
Google for "omniweb 5.5 sneaky peak". The current release is very stable on my system.

I do currently use the sneaky peeks, but I haven't switched it over as my default browser, so I still keep a lot of sites open in Safari. I was mainly using the Safari problem as an example as to situations that Wil's idea would potentially help with, but it does happen.

July 18, 2006 4:51 AM

 
Blogger Andrew Garber said...

The inter-document communication problem could be solved by using session-based plist files. In addition to your persistent preference files, you could have per-session files that are created when applications are launched, and deleted when applications quit. Writes/read to/from these session files would have to be atomic.

July 18, 2006 6:40 PM

 
Anonymous Anonymous said...

Which instance would handle the menu bar, and what happens if this instance crashes? The user loses the ability to spawn new documents.

July 18, 2006 10:04 PM

 
Blogger Abhi Beckert said...

They would all handle the menubar independently, a separate menubar for each app, just like we have now.

July 22, 2006 3:02 AM

 
Anonymous Shaun said...

Betcha wish Apple had bought BeOS instead of NeXT, right?

...every time I look at the Intel roadmap. Surely there are enough ex-BeOS guys now at Apple that could influence a change to a more threaded model of development and provide a better API for it so that it's less of a chore creating multi-threaded apps?

July 22, 2006 8:09 AM

 
Anonymous joek said...

You can open up multiple instances of a Macintosh application from Terminal. For instance:

/Applications/Safari.app/Contents/MacOS/Safari&

Type !! a couple of times to launch multiples.

It's not recommended, but it's kind of fun. Hopefully won't do much lasting damage.

July 31, 2006 11:38 AM

 

Post a Comment

<< Home