Non-blocking I/O: What can be done?
Terje Slettebø (285) 275 posts |
Colleagues, While it’s great that we’ve got the BeagleBoard platform, it still appears unreasoably sluggish in some areas, in particular filing operations. For example, when doing a disk syncronisation with a backup disk, the whole system becomes generally unresponsive (when choosing the “Faster” option), and remains that way for the many hours a backup on this system needs. I wouldn’t mind too much the speed of I/O operations (which may be caused by a combination of the USB protocol and the driver software) had it not been for that it more or less freezes the system while it does I/O… Also, while it’s great that a new version of the BeagleBoard, BeagleBoard Xm, is under way, I suspect that its faster CPU will not solve this problem, as I suspect the filing operations are I/O bound, rather than CPU bound… So what causes the sluggishness and high CPU use when doing I/O on RISC OS? Well, I’m no expert on this, but I suspect the problem is due to blocking I/O: When making a system call to do I/O, at some point it waits for a device to return with a response, or a buffer full/empty event. So what does RISC OS do while it waits for the response? Well, basically nothing… I don’t know that ccode in detail, but I suspect it just waits in a poll loop until the device is ready. In the mean time, nothing can happen in RISC OS (except interrupt routines). In particular, other tasks can’t get their share of the CPU, to keep the system responsive. What I’m wondering is this: Might we change RISC OS so that it calls Wimp_PollIdle while it waits for I/O? Essentially the system would call Wimp_Poll on the task’s behalf. As long as the call returns Null Event, it should be uncomplicated, but given that the application is still single-threaded, having any other code returned could be difficult… One possible way of handling it might be just to “bounce” any non-Null Events: Send them back to the system using Wimp_SendMessage to be picked up by the main polling loop. Naturally, this could introduce its own inefficiencies (especially if the same messages are bounced multiple times), so ideally, we should have been able to call Wimp_PollIdle with a mask excluding every event except the Null Event, queuing the others for delivery to the main polling loop, when the I/O operation completes. If such a scheme could be made to work, the application itself would still remain unresponsive during I/O operations (which would be the case even in a preemtive multitasking system), but, importantly, other tasks should be able to run uninterrupted, including other I/O operations. What do you think? Might this be a workable solution? Any other potential solutions to the blocking I/O problem? Naturally, with a preemtive multitasking system, this would no longer be a problem, so cooperative multitasking and blocking I/O is not a good combination. Making RISC OS do preemtive multitasking pervasively may be a large undertaking, and maybe making the step to non-blocking I/O (using the above, or some other scheme) could be a reasonable solution for a substantial improvement at modest development cost. |
Jeffrey Lee (213) 6048 posts |
As you can probably guess, this has already been discussed a couple of times previously :) As far as I can see there are basically three approaches:
|
Jess Hampshire (158) 865 posts |
Given how horrid it is trying to use my Iyonix for anything while accessing USB storage, this must be a real hit to the BeagleBoard, running RO from it. I would assume decent caching would mitigate the situation to quite a good extent. If a proper non blocking system isn’t viable, would a partially blocking system be possible? (Perhaps as part of a PMT system), ie, new apps don’t block, but legacy ones do. |
Jeffrey Lee (213) 6048 posts |
It’s a lot better than it was before I did the performance improvements! Running the boot sequence from USB used to be horrendous, because of all the tiny scripts that got executed.
Yes. |
Jess Hampshire (158) 865 posts |
Is that still a generic !boot? Is it released? And if so, should Iyonix users update? |
Jeffrey Lee (213) 6048 posts |
It’s the !boot that’s available from here, as either the self-extracting HardDisc4 or the tar’d+bzip’d HardDisk4. And no, I don’t know why ‘disc’ is spelt differently between the two :) You can try updating your Iyonix to use it if you want, but I don’t think anyone’s given it any proper testing on the Iyonix yet. Also I think the only real improvements that have been made to the boot sequence were the SCSISoftUSB optimisations, which you can update independently |
Terje Slettebø (285) 275 posts |
Yes, I should probably have guessed that… :) However, it’s not always easy to find any past threads on a topic, given that they may have used different names for things… Searching for “non-blocking I/O”, for example, in the forum search, turns up no results. Thanks for summarising the options in this issue. I guess one thing contributing to my frustration was that I thought SyncDiscs was multitasking, when in fact it wasn’t, until recently... I just thought that it rarely yielded to the OS and/or its filing operations where very CPU/network intensive… I’ll read up on the things you mentioned, and the pages referenced. Just one quick note, though: Given that a lot of our RISC OS software is no longer being maintaned and/or the source is not available, requiring a change in the software to get benefits from non-blocking I/O may not be very practical (at least as the only solution), given that a large amount of the existing software would not benefit from it. |
Jess Hampshire (158) 865 posts |
If the situation were that old apps were to still block i/o, it would only hit system performance when they are actually performing I/O, wouldn’t it? Since most old apps don’t perform much file access, this wouldn’t often be a disaster. And the worst case would be performance like the current system anyway. It is during filer actions that the system really suffers. If a new app only non-blocking I/O system were far easier to do than a system that works fully with all apps, I think it would be preferable. (I presume it would be far more likely to be stable, for example.) |
Steffen Huber (91) 1953 posts |
As Jeffray said previously, the first priority should be to forget about cunning ways to introduce non-blocking I/O and concentrate on optimising various parts of our current system. The USB stack and the mass storage driver, the network stack, and thinking about replacing Filecore with something more sensible for the future are obvious first steps. Especially adding non-blocking I/O in a way that would let old apps profit is IMHO much too risky. Old apps are non-I/O-intensive anyway, mainly because I/O performance was always dire on RISC OS systems (with the possible exception of the UDMAd harddisc access on the IYONIX). |