Adept Software Development

Adept: (A)pplication (D)evelopment (E)nterprise to (P)ersonal (T)ransition. It is a system I am developing to leverage Enterprise developer skills to produce stand-alone software for other market segments. This is a general software development blog discussing issues about project, architecture, design and development. The emphasis will be in Java, but many of the issues will be more general. Almost all will be technical.

http://marringtons.com

Thursday, June 02, 2005

Cooperative Multi-Tasking - Yesteryear and Today

I've been developing for and with multi-tasking systems since what feels like the dawn of time, but in actuality was the late seventies. Those were the last days of total dominance by mainframe or mini-computer on the desktop. Even the smallest computer was too expensive to be dedicated to one user or program. IBM were doing great things with virtual machines - making it appear as if each user had a whole IBM mainframe at their personal disposal. So-called minicomputers used multi-tasking so that individual applications (including the operating system itself) could have a share of CPU and memory.

Then came the micro-computer and PC. The users loved the freedom from expensive shared computers, but the first ones lacked the grunt for true multi-tasking - although Digital Research gave it a go with MPM and Concurrent CPM. This was when Microsoft first won the race by providing DOS to IBM. No multi-tasking. I can remember people starting spreadsheet calculations that would take up to two days - during which time their $5,000 computer could only be used as a paperweight.

Microsoft 'to the rescue' again with Windows 3 (the first non-geek popular version of Windows). Windows had originally been developed for the 8086 with little or no hardware support and an ability to make very small yet powerful programs. Only when the 80386 chip was available did system have memory and hardware support for multiple programs.

Windows 3 and it's even more popular networking offspring 3.11 were still built on the old 16 bit code. They inherited a multi-tasking method called co-operative multi-tasking. In this model a process or program truly does own the CPU until it calls an operating system service to release control and schedule the next task waiting for CPU. Those of us used to working with 'true' multi-tasking were fairly unimpressed with such a primative system. Yet, it worked amazingly well. This is because most programs spend most of their time waiting for user input. As long as they followed the well documented standard of having a primary loop that released the CPU for others while waiting, the used very little CPU.

And here's the rub. With the release of Windows 95 and true multi-tasking we see more inconsistent responsiveness and more user delays than in the 'primative' cooperative multi-tasking days. Even today with machines more than 10 times faster with almost 10 times as much memory, I can suffer noticable delays waiting for a web page to render while doing a large Java compile.

Certainly one reason is that we expect a modern computer to do many things at once, but the other reason - and the one I want to talk about here - is the sense of responsibility. With co-operative multi-tasking, the developer was overtly responsible for end-user performance. Even when doing a complex calculation or compile, a good developer would ensure that the system yielded control often enough so that the user interface did not become sticky.

With a return to the Unix fold of time-sharing multi-tasking, the responsibility goes back to the operating system and the developer is taught to ignore it. The former is good since the operating system can do a much better job of it - and it simplifies the code. The latter is not so good. The operating system attempts to discern user interface code and give it priority. This is why the mouse does not usually stick no matter how hard the computer is working. It's much harder to differentiate user interface calculations within a program from less important batch operations. This is why my browser rendering is delayed by the Java compile.

The resolution in native code is relatively obvious. Before a processor intensive operation, reduce the priority of the process with an operating system service and restoring it to normal when returning to interactive mode. This way other user interface programs should get priority and be less likely to be delayed.

This doesn't work if your code is further removed from the operating system. Don't mistake light-weight Java threads with OS level multi-tasking. It's light-weight because it shares the JVM cpu time between threads. Since the JVM is just a program to the operating system, it takes it's normal slice of computer resources and then divides it up among it's active threads.

The only way I can think of to release cpu resources to other programs during a long calculation or compile would be to sleep for one millisecond fairly regularly. I don't like it. Firstly it reeks of polling, and secondly your process will be unnecessarily delayed if no-one else needs the CPU.

In the case of a compile or build there is another option. They are such large processes that they can spawn their own independant JVM. It should be possible to tell the operating system to run these JVMs at a lower priority.

In truth modern CPUs are so over-powered that no-one except extreme power users would even notice. The larger bottleneck is around sharing disk access time rather than CPU time. This is a discussion for another day.

0 Comments:

Post a Comment

<< Home