Microthreading Mono
Friday, May 5th, 2006 at 5:26 PM by: babbagelindenBeing able to add an independent, event driven program to any object in the world makes scripting in Second Life really intuitive: you add a script and your object becomes an independent agent able to sense its world through event handlers, sit and think and then effect the world through library calls. It’s a model that works equally well whether you’re coding a fish which swims around looking for food or an information post that just hands out notecards whenever it’s poked.
It’s an approach that quickly leads to lots of running scripts. Some of the more complex regions constantly run 1000s of scripts. Abbotts Aerodrome runs around 2000 scripts and while most of these are of the give notecard when poked variety they could just as well be calculating PI or running SETI at Home, which means they all need to behave as if they were independent processes running concurrently within the simulator.
Supporting such high levels of concurrency has been one of the major challenges in integrating Mono in to Second Life. Although Mono and the CLI support the concept of independent threads of execution, each Mono thread maps on to an operating system thread which tend to be fairly heavyweight. By default most operating systems reserve megabytes of memory for each thread and don’t cope with more than a few dozen running concurrently. Even reducing the allocated stack size to 32K and using the latest thread libraries on Linux doesn’t get you much past 1000 running threads before the system starts to wheeze.
The other difficulty with Second Life scripts is that they can migrate between simulators while they are running. You are perfectly entitled to write a script which never stops running and then to tie it to a rocket that you fire in to another region. This is relatively easy to do when all of your script state is in a single 16K block, but much harder when your script has been Just In Time compiled to machine code and its state is scattered throughout memory, registers and an operating system thread.
The solution we implemented for Second Life was to use RAIL on top of .NETs Reflection and Reflection.Emit facilities to inject microthreading in to the script assemblies, an approach used by the JavaGoX and Brakes projects to implement mobile agents in Java. Our microthread injector searches through the script assembly finding points where the script should yield and inducing the types on the stack at those points. It can then inject extra opcodes in to the assembly which copy the stack in to a heap object and cause the script to yield. Whenever a script yields we can restore another script from its previously saved heap object and start it running again, allowing us to schedule many microthreaded scripts on a single operating system thread. By marking the heap objects as serializable we can then just use the standard .NET communication facilities to migrate scripts to remote simulators where they can continue running.
The approach is memory efficient as the memory needed to save the microthread is allocated when it yields, so a large amount of stack space doesn’t need to be conservatively reserved up front for the thread. The problems with this approach is that it is expensive in CPU time spent switching microthreads and the space taken up by injected opcodes.
An alternative approach to microthreading Mono has been taken by Tomi Valkeinen who has written some very funky code (inspired by Eve Online’s use of Stackless Python) to save and restore the native stack to switch between microthreads. This approach should be a lot faster than opcode injection. We can’t currently use Tomi’s microthreads for Second Life as the saved stack may contain pointers which can’t be transferred to a remote machine, but it may be possible in the future to use Mono’s garbage collector to identify the pointers in the native stack and twizzle them in to a form that can be sent to a remote machine.
It would be very cool to build a library which automatically switched between Tomi’s microthreading implementation on Mono and Linden Lab microthreading on .NET. People could then build portable microthreaded applications which take advantage of Mono’s native microthreading when it’s available.


June 7th, 2006 at 9:11 AM
What was the rationale for choosing Mono over Stackless Python?
Will
June 8th, 2006 at 8:11 AM
It’s address space, not physical memory, that most operating systems reserve for each thread.
June 8th, 2006 at 11:34 AM
Because python is slow as shit that’s why
June 10th, 2006 at 5:52 PM
Perhaps, “duh”, but your flippant attitude doesn’t inspire confidence in your assertion. Stackless Python is used by the folks at Eve who run the largest non-sharded MMORPG and thus has a proven track record so I think it’s a reasonable question to ask.
Personally I prefer mono and am glad Linden Labs is putting in the time to add these capabilities to mono. Nevertheless, I’d like to know what advantages mono will have over SP. If there are good reasons I’ll personally lobby the Eve devs to consider using mono in the future.
Will
June 11th, 2006 at 10:34 AM
Will, Stackless may well have been a good choice too. The stackless microthreading implementation is certainly mature and proven through its use in Eve. The attraction of Mono is that we want to support the use of mainstream languages to script Second Life alongside maintaining compatability with existing LSL scripts and allowing LSL to be used to develop new scripts in the future. The CLI and Mono are particularly attractive from this perspective. Hilmar Petursson, the CEO of CCP was very interested in the prospect of a microthreaded CLI when I spoke to him about it at the Austin Games Conference last year.
June 11th, 2006 at 6:01 PM
I believe the decision for using mono is based more on then just threading. It’s the JIT that most appeals to LL and garabage collection, as well as the common byte code (CIL) that make up Mono that makes it a win over python. Now if you like Python, you can always use IronPython.
June 19th, 2006 at 1:24 AM
Well, if you can’t change the LSL VM cause you don’t own it, then yeah, I’d go with SP.
Mono is not what you’re looking for..
June 21st, 2006 at 2:07 PM
I’m delighted you’re thinking Mono. I think every day about how wonderful it will be to use it instead of LSL. I’m just not as big a fan of Python as C#. So don’t be discouraged by these naysayers!
June 22nd, 2006 at 12:29 AM
Let me reframe the problem.. can you think of an environment similar to SL in which Mono has been a success in?
July 11th, 2006 at 1:36 AM
I like where this is headed, although I don’t understand the comment that “Python is slow.” Maybe Stackless Python is slow, but the Eve crew seem to have done fine with it. But IronPython and C# take exactly the same amount of time to chew through my ridiculous recursive Sudoku solver… whatever THAT number’s worth…
On the topic of Mono, though, I understand LSL is going to remain the sole scripting language of SL for some time, with no ETA on other langauges being added… BUT I’m optimistic, and hope IPy makes it at least. As it stands, I’m using my own converter (”slython”) to generate LSL from Py source because I got sick of having to call a function just to access a list member. =)
July 14th, 2006 at 5:05 PM
“I think every day about how wonderful it will be to use it instead of LSL.”
I think it unlikely that you’ll be able to use anything other than LSL even after the underlying implementation is using Mono.
What I’d like to know is whether their microthreading scheduler is still going to poll every script every frame for triggering events. And if not, why they don’t start out by fixing their current bytecode interpreter?
October 19th, 2008 at 3:14 AM
thank you