Stackless Python in EVE Kristján Valur Jónsson [email_address] CCP Games inc.
EVE <ul><li>MMORPG Space game </li></ul><ul><li>Client / server </li></ul><ul><li>Single shard massive server </li></ul><u...
The Tranquility cluster <ul><li>400 GHz CPU / 200 Gb RAM </li></ul><ul><li>2 Routers (CISCO Alteon) </li></ul><ul><li>14 P...
EVE Architecture <ul><li>COM-like basic architecture </li></ul><ul><li>Python tighly integrated at an early stage </li></u...
Stackless Python <ul><li>Tasklets </li></ul><ul><ul><li>Threads of execution.  Not OS threads </li></ul></ul><ul><ul><li>L...
Stackless? <ul><li>No C stack </li></ul><ul><ul><li>Python stack in linked frame objects </li></ul></ul><ul><ul><li>Taskle...
Channels
Channel semantics <ul><li>Send on a channel with no receiver blocks tasklet. </li></ul><ul><li>Send on a channel with a (b...
Channel semantics, cont. <ul><li>Scheduling semantics are precise: </li></ul><ul><ul><li>A blocked tasklet is run immediat...
Stackless in EVE <ul><li>BLUE foundation: robust, but cumbersome </li></ul><ul><li>RAD </li></ul><ul><li>Stackless Python:...
The main loop <ul><li>Establish stackless context </li></ul><ul><li>int WinMain(...)  { </li></ul><ul><ul><li>PyObject *my...
<ul><li>Regular Windows message loop </li></ul><ul><li>Runs in Stackless context </li></ul><ul><li>The  “Main Tasklet” </l...
Autoexec.py import blue def Startup(): import service srvMng = service.ServiceManager() run = [&quot;dataconfig&quot;, &qu...
Tickers <ul><li>Tickers are BLUE modules: </li></ul><ul><ul><li>Trinity (the renderer) </li></ul></ul><ul><ul><li>Netclien...
The PyOS tick: <ul><li>Runs fresh tasklets </li></ul><ul><ul><li>(sleepers awoken elsewhere) </li></ul></ul>Tick() { … mSy...
blue.pyos.synchro <ul><li>Synchro: </li></ul><ul><ul><li>Provides Thread-like tasklet utilities: </li></ul></ul><ul><ul><u...
<ul><li>Sleep:  A python script makes the call  blue.pyos.Sleep(200) </li></ul><ul><li>C++ code runs: </li></ul><ul><ul><l...
blue.pyos.synchro, ctd. <ul><li>Main tasklet in windows loop enters PyOS::Tick() </li></ul><ul><li>mSleepers are examined ...
Points to note: <ul><li>A tasklet goes to sleep by calling  PyChannel_Receive()  on a channel which has no pending sender....
Socket Receive <ul><li>Use Windows asynchronous file API </li></ul><ul><li>Provide a synchronous python API.  A python scr...
Receive, cont. <ul><li>Python script runs: foo, bar = socket.Read() </li></ul><ul><li>C code executes the request: </li></...
Receive, cont. <ul><li>Socket server is ticked from main loop </li></ul><ul><li>For all requests that are marked completed...
Receive completed
Main Tasklet <ul><li>The one running the windows loop </li></ul><ul><li>Can be suspended, allowing other tasklets to run <...
Channel magic <ul><li>Channels perform the stackless context switch. </li></ul><ul><li>If there is a C stack in the call c...
Co-operative multitasking <ul><li>Context is switched only at known points. </li></ul><ul><ul><li>In Stakcless, this is ch...
Tasklets <ul><li>Tasklets are cheap </li></ul><ul><li>Used liberally to reduce perceived lag </li></ul><ul><ul><li>UI even...
Example: UI Event: <ul><li>Main tasklet receives window messages such as WM_CLICK </li></ul><ul><li>Trinity invokes handle...
That’s all <ul><li>For more info: </li></ul><ul><ul><li>http://www.ccpgames.com </li></ul></ul><ul><ul><li>http://www.eve-...
Upcoming SlideShare
Loading in...5
×

Stackless Python In Eve

28,960

Published on

Published in: Technology
3 Comments
20 Likes
Statistics
Notes
  • Check out all kinds of python info at http://www.rootninja.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Does anyone know details about the BLUE object about which he is talking?
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • thanq its really nice along with helpful to me in thinking about innovation comes as well as think of which.... very nice work.... tanq for this.....
    Teisha
    http://dashinghealth.com http://healthimplants.com
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
No Downloads
Views
Total Views
28,960
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
583
Comments
3
Likes
20
Embeds 0
No embeds

No notes for slide

Transcript of "Stackless Python In Eve"

  1. 1. Stackless Python in EVE Kristján Valur Jónsson [email_address] CCP Games inc.
  2. 2. EVE <ul><li>MMORPG Space game </li></ul><ul><li>Client / server </li></ul><ul><li>Single shard massive server </li></ul><ul><li>120.000 active players, >24.000 concurrent users </li></ul><ul><li>World concurrency record on a shard </li></ul><ul><li>Relies on Stackless Python </li></ul>
  3. 3. The Tranquility cluster <ul><li>400 GHz CPU / 200 Gb RAM </li></ul><ul><li>2 Routers (CISCO Alteon) </li></ul><ul><li>14 Proxy servers (IBM Blade) </li></ul><ul><li>55 Sol servers (IBM x335) </li></ul><ul><li>2 DB servers (clustered, IBM Brick x445) </li></ul><ul><li>FastT600 Fiber, 56 x FC 15k disks, DS4300 + 3*EXP700 </li></ul><ul><li>Windows 2000, MS SQL Server </li></ul><ul><li>Currently being upgraded </li></ul><ul><ul><li>AMD x64 </li></ul></ul>
  4. 4. EVE Architecture <ul><li>COM-like basic architecture </li></ul><ul><li>Python tighly integrated at an early stage </li></ul><ul><li>Home-grown wrapping of BLUE objects </li></ul>
  5. 5. Stackless Python <ul><li>Tasklets </li></ul><ul><ul><li>Threads of execution. Not OS threads </li></ul></ul><ul><ul><li>Lightweight </li></ul></ul><ul><ul><li>No pre-emption </li></ul></ul><ul><li>Channels </li></ul><ul><ul><li>Tasklet rendezvous point </li></ul></ul><ul><ul><li>Data passing </li></ul></ul><ul><ul><li>Scheduling </li></ul></ul><ul><ul><li>Synchronization </li></ul></ul>
  6. 6. Stackless? <ul><li>No C stack </li></ul><ul><ul><li>Python stack in linked frame objects </li></ul></ul><ul><ul><li>Tasklet switching by swapping frame chain </li></ul></ul><ul><li>Compromise </li></ul><ul><ul><li>stackless where possible. </li></ul></ul><ul><ul><li>C stack whisked away if necessary </li></ul></ul>
  7. 7. Channels
  8. 8. Channel semantics <ul><li>Send on a channel with no receiver blocks tasklet. </li></ul><ul><li>Send on a channel with a (blocked) receiver, suspends tasklet and runs receiver immediately. Sender runs again in due course. </li></ul><ul><li>Symmetric wrt. Send and Receive. </li></ul><ul><li>“ balance”, can have a queue of readers or writers. </li></ul><ul><li>Conceptually similar to Unix pipes </li></ul>
  9. 9. Channel semantics, cont. <ul><li>Scheduling semantics are precise: </li></ul><ul><ul><li>A blocked tasklet is run immediately </li></ul></ul><ul><li>Usable as a building block: </li></ul><ul><ul><li>semaphores </li></ul></ul><ul><ul><li>mutex </li></ul></ul><ul><ul><li>critical section </li></ul></ul><ul><ul><li>condition variables </li></ul></ul>
  10. 10. Stackless in EVE <ul><li>BLUE foundation: robust, but cumbersome </li></ul><ul><li>RAD </li></ul><ul><li>Stackless Python: Python and so much more </li></ul><ul><li>EVE is inconceivable without Stackless </li></ul><ul><li>Everyone is a programmer </li></ul>
  11. 11. The main loop <ul><li>Establish stackless context </li></ul><ul><li>int WinMain(...) { </li></ul><ul><ul><li>PyObject *myApp = new EveApp(); </li></ul></ul><ul><ul><li>PyObject *r = PyStackless_CallMethod_Main(MyApp, “WinMain”, 0); </li></ul></ul><ul><ul><li>return PyInt_AsLong( r ); </li></ul></ul>
  12. 12. <ul><li>Regular Windows message loop </li></ul><ul><li>Runs in Stackless context </li></ul><ul><li>The “Main Tasklet” </li></ul>The main loop cont. PyObject* EveApp::WinMain(PyObject *self, PyObject *args) { PyOS->ExecFile(&quot;script:/sys/autoexec.py&quot;); MSG msg; while(PeekMessage(&msg, 0, 0, 0, PM_REMOVE)){ TranslateMessage(&msg); DispatchMessage(&msg); } for (TickIt i = mTickers.begin(; i != mTickers.end(); i++) i->mCb-> OnTick (mTime, (void*)taskname); }
  13. 13. Autoexec.py import blue def Startup(): import service srvMng = service.ServiceManager() run = [&quot;dataconfig&quot;, &quot;godma&quot;, “ui&quot;, …] srvMng.Run(run) #Start up the client in a tasklet! if CheckDXVersion(): import blue blue.pyos. CreateTasklet (Startup, (), {})
  14. 14. Tickers <ul><li>Tickers are BLUE modules: </li></ul><ul><ul><li>Trinity (the renderer) </li></ul></ul><ul><ul><li>Netclient </li></ul></ul><ul><ul><li>DB (on the server) </li></ul></ul><ul><ul><li>Audio </li></ul></ul><ul><ul><li>PyOS (special python services) </li></ul></ul><ul><ul><li>… </li></ul></ul>
  15. 15. The PyOS tick: <ul><li>Runs fresh tasklets </li></ul><ul><ul><li>(sleepers awoken elsewhere) </li></ul></ul>Tick() { … mSynchro->Tick() PyObject *watchdogResult; do { watchdogResult = PyStackless_RunWatchdog(20000000); if (!watchdogResult) PyFlushError(&quot;PumpPython::Watchdog&quot;); Py_XDECREF(watchdogresult); } while (!watchdogResult);
  16. 16. blue.pyos.synchro <ul><li>Synchro: </li></ul><ul><ul><li>Provides Thread-like tasklet utilities: </li></ul></ul><ul><ul><ul><li>Sleep(ms) </li></ul></ul></ul><ul><ul><ul><li>Yield() </li></ul></ul></ul><ul><ul><ul><li>BeNice() </li></ul></ul></ul>
  17. 17. <ul><li>Sleep: A python script makes the call blue.pyos.Sleep(200) </li></ul><ul><li>C++ code runs: </li></ul><ul><ul><li>Main tasklet check </li></ul></ul><ul><ul><li>sleeper = New Sleeper(); mSleepers.insert(sleeper); PyObject *r = PyChannel_Receive(sleeper->mChannel); </li></ul></ul><ul><ul><li>Another tasklet runs </li></ul></ul>blue.pyos.synchro cont.
  18. 18. blue.pyos.synchro, ctd. <ul><li>Main tasklet in windows loop enters PyOS::Tick() </li></ul><ul><li>mSleepers are examined for all that are due we do: </li></ul><ul><ul><li>mSleepers.remove(sleeper); PyChannel_Send(sleepers.mChannel, Py_NONE); </li></ul></ul><ul><li>Main tasklet is suspended (but runnable), sleeper runs. </li></ul>
  19. 19. Points to note: <ul><li>A tasklet goes to sleep by calling PyChannel_Receive() on a channel which has no pending sender. </li></ul><ul><li>It will sleep there (block) until someone sends </li></ul><ul><li>Typically the main tasklet does this, doing PyChannel_Send() on a channel with a reader </li></ul><ul><li>Ergo: The main tasklet may not block </li></ul>
  20. 20. Socket Receive <ul><li>Use Windows asynchronous file API </li></ul><ul><li>Provide a synchronous python API. A python script calls Read(). </li></ul><ul><li>Tasklet may be blocked for a long time, (many frames) other tasklets continue running. </li></ul><ul><li>Do this using channels. </li></ul>
  21. 21. Receive, cont. <ul><li>Python script runs: foo, bar = socket.Read() </li></ul><ul><li>C code executes the request: </li></ul><ul><ul><li>Request *r = new Request(this); WSAReceive(mSocket, …); mServe->insert( r ); PyChannel_Receive(r->mChannel); </li></ul></ul><ul><li>Tasklet is suspended </li></ul>
  22. 22. Receive, cont. <ul><li>Socket server is ticked from main loop </li></ul><ul><li>For all requests that are marked completed, it transfers the data to the sleeping tasklets: </li></ul><ul><li>PyObject *r = PyString_FromStringAndSize(req->mData, req->mDataLen); PyChannel_Send(req->mChannel, r); Py_DECREF(data); delete req; </li></ul><ul><li>The sleeping tasklet wakes up, main tasklet is suspended (but runnable) </li></ul>
  23. 23. Receive completed
  24. 24. Main Tasklet <ul><li>The one running the windows loop </li></ul><ul><li>Can be suspended, allowing other tasklets to run </li></ul><ul><li>Can be blocked, as long as there is another tasklet to unblock it (dangerous) </li></ul><ul><li>Is responsible for waking up Sleepers, Yielders, IO tasklets, etc. therefore cannot be one of them </li></ul><ul><li>Is flagged as non-blockable ( stackless.get_current().block_trap = True ) </li></ul>
  25. 25. Channel magic <ul><li>Channels perform the stackless context switch. </li></ul><ul><li>If there is a C stack in the call chain, it will magically swap the stacks. </li></ul><ul><li>Your entire C stack (with C and python invocations) is whisked away and stored, to be replaced with a new one. </li></ul><ul><li>This allows stackless to simulate cooperative multi-threading </li></ul>
  26. 26. Co-operative multitasking <ul><li>Context is switched only at known points. </li></ul><ul><ul><li>In Stakcless, this is channel.send() and channel.receive() </li></ul></ul><ul><ul><li>Also synchro.Yield(), synchro.Sleep(), BeNice(), socket and DB ops, etc. </li></ul></ul><ul><li>No unexpected context switches </li></ul><ul><ul><li>Almost no race conditions </li></ul></ul><ul><ul><li>Program like you are single-threaded </li></ul></ul><ul><ul><li>Very few exceptions. </li></ul></ul><ul><ul><li>This extends to C state too! </li></ul></ul>
  27. 27. Tasklets <ul><li>Tasklets are cheap </li></ul><ul><li>Used liberally to reduce perceived lag </li></ul><ul><ul><li>UI events forked out to tasklets </li></ul></ul><ul><ul><ul><li>A click can have heavy consequences. </li></ul></ul></ul><ul><ul><ul><ul><li>Heavy logic </li></ul></ul></ul></ul><ul><ul><ul><ul><li>DB Access </li></ul></ul></ul></ul><ul><ul><ul><ul><li>Networks access </li></ul></ul></ul></ul><ul><ul><li>special rendering tasks forked out to tasklets. </li></ul></ul><ul><ul><li>controlling an audio track </li></ul></ul><ul><li>“ tasklet it out” </li></ul><ul><li>Use blue.pyos.synchro.BeNice() in large loops </li></ul>
  28. 28. Example: UI Event: <ul><li>Main tasklet receives window messages such as WM_CLICK </li></ul><ul><li>Trinity invokes handler on UI elements or global handler </li></ul><ul><li>Handler “tasklets out” any action to allow main thread to continue immediately. </li></ul>def OnGlobalUp(self, *args): if not self or self.destroyed: return mo = eve.triapp.uilib.mouseOver if mo in self.children: uthread.new(mo._OnClick) class Action(xtriui.QuickDeco): def _OnClick(self, *args): pass
  29. 29. That’s all <ul><li>For more info: </li></ul><ul><ul><li>http://www.ccpgames.com </li></ul></ul><ul><ul><li>http://www.eve-online.com </li></ul></ul><ul><ul><li>http://www.stackless.com </li></ul></ul><ul><ul><li>[email_address] </li></ul></ul>
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×