Hi,
rdos wrote:Owen wrote:Brendan wrote:
- Lack of prioritised asynchronous IO: While most (all?) OSs support asynchronous IO and most OSs support prioritised IO; application programmers rarely use it to improve performance. This is partly because the APIs being used are obsolete (e.g. "read()") and/or too messy (POSIX asynchronous IO) and/or inadequate (still no "aio_open()"?).
Also on many systems (E.G. Linux) support for AIO is limited to verging on non-existant (Kernel support is minimal; userspace support is emualted using threads). POSIX only supports waiting on file descriptors traditionally and AIO using (realtime) signals and select; realtime signals are not widely implemented, and signals themselves have problems in general.
This is an area where POSIX could learn a lot from
Windows NT 3...
IMO, both the POSIX and Win32 AIO is too complex, non-portable, and does not offer any advantage over creating more threads instead. RDOS has no AIO-interface, as I don't think this is a good idea. If you need parallell IO, create a new thread and do the IO there instead. AIO is for mono-tasking.
For an example, imagine an image viewer. There's a directory containing 50 photos; and the user clicks on one of the photos. However, you know it's likely that the user will probably move forward/backward through all the photos and/or enable the "slide show" feature; so you want to pre-load all 50 photos in the background.
The photo the user clicked on needs to be loaded as "high priority" and displayed as quickly as possible; the next photo needs to be loaded as "medium priority" so that its file IO doesn't slow down the "high priority" file IO; and in the same way the other photos need to be loaded at progressively lower priorities. Basically, the priority of file IO for each photo being loaded/pre-loaded depends on the photo's "distance" from the photo currently being displayed.
While all this loading/pre-loading is happening, the user is moving forward/backward through all the photos. If the photo currently being displayed keeps changing, and priority of file IO for each photo depends on the "distance" from the currently displayed photo; then the priority of file IO for each photo being loaded/pre-loaded should also change. For example, maybe the user started at "photo #1" and you told the OS to pre-load "photo #9" at a very low priority, but then the user clicked on the "next photo" button 7 times and now you're displaying "photo #8"; so you tell the OS to change the priority of the file IO for "photo #9" to "medium/high".
Of course there's also memory constraints - there's 50 photos, but you've only got enough memory to hold 25 photos. As the user is moving through all the photos you need to be discarding "less likely to be needed" photos to free up memory and cancelling any file IO that is no longer necessary, and starting file IO for photos that become more likely to be needed.
There's also decoding. You don't just want to pre-load the photos, you want to pre-decode the JPGs into raw pixel data so that when the user clicks on the "next photo" button it can be displayed faster. Don't forget about the memory constraints though - maybe you've got enough memory to have 12 of the photos loaded and decoded, and 13 photos loaded but not decoded. Of course for the 4 "most likely to be needed soon" photos you also want to upload the data into display memory, so that those photos can be displayed with an extremely fast 2D accelerated "display memory to display memory" bit blit, and so that when the user clicks on the "next photo" button the next photo is displayed instantly.
Now, you're not using asynchronous file IO. Instead, you've got 50 threads (potentially all fighting for the same CPU/s) plus one main thread responsible for organising everything and displaying the current photo. Every time the user clicks on the "next photo" button the main thread unleashes a storm of thread switches as it tries to re-synchronise all those 50 threads. You're also dealing with lock contention and race conditions and who knows what else.
Remember this:
Brendan wrote:[*]Scalability: It's still a major problem. Lots of software is still "single threaded" (and I suspect that a lot of software that is multi-threaded isn't as well designed as it could be).
That's right - most application developers simply will not bother with any of this. They'd look at everything above and decide it's too hard and give up. They'll use plain file IO without any threads, without any priorities and without any pre-loading; and each time the user clicks on the "next photo" button there's going to be noticeable lag before the next photo is displayed. The user is going to think the image viewer is laggy. What about other applications? If the user thinks every application is slow/laggy then the user is going to blame the OS and not the applications. So, how do you make it easier for application developers?
Asynchronous file IO should make this image viewer a lot easier to write. You'd have one high priority thread doing all the synchronisation and file IO; and maybe a few "worker threads" for decoding images (e.g. no more than one worker thread per CPU). Almost all of the hassle of synchronising the threads (and the locks, race conditions, etc) disappears; and the "unleashes a storm of thread switches" problem is gone too.
Unfortunately, I believe you (and Owen) are right: asynchronous file IO is badly implemented and badly supported on most existing OSs. Asynchronous file IO should make the image viewer a lot easier to write, but probably won't.
Cheers,
Brendan