[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: Question about multi-threading in Lua
- From: askok@...
- Date: Fri, 16 May 2008 12:15:33 +0300
I would see your case being okay using either mechanism.
In general, coroutines are faster and always portable
(since they require no OS side support). It comes to how
much isolation / synchronization you wish to have between
the states. Coroutines have low isolation, high
synchronization). Real OS threading has high isolation,
low synchronization (varies by the toolkits).
One issue to keep in mind is multicore support. Coroutines
always burden just a single core. OS threading will be
balanced on all available cores.
Below is my ever-changing map of the Lua multithreading
solutions (included in Lua Lanes manual).
-asko
==================
Lua coroutines (by Lua authors)
==================
http://www.lua.org/manual/5.1/manual.html#2.11
http://lua-users.org/wiki/CoroutinesTutorial
Lua coroutines is an integral part of Lua 5 itself. It is
listed here, since
it should be the _first_ multitasking mechanism to
consider. It can also be
used together with Lanes, or the other mechanisms listed
below.
Coroutines are very usable in provider/consumer
situations, allowing you to
queue Lua functions on an as-needed dataflow basis with
each other.
Pros:
- works with plain Lua (no extensions)
- works on any platform
- lightweight (no OS level threading or locking
involved)
Cons:
- co-operative, meaning your code will need to
decide, who gets to run
- does not utilize multiple CPUs/cores
=============
LuaThread (by Diego Nehab)
=============
http://www.cs.princeton.edu/~diego/professional/luathread/
LuaThread provides thread creation, mutexes, condition
variables, and inter-
thread queues to the Lua scripts. It takes a C-kind of
approach, where Lua
globals are shared by the threads running, and need
therefore to be guarded
against multithreading conflicts.
Whether this is exactly what you want, or whether a more
loosely implemented
multithreading (s.a. Lanes) would be better, is up to you.
One can argue that
a loose implementation is easier for the developer, since
no application level
lockings need to be considered.
Pros:
- no marshalling (data serialization) overhead, since
threads share the
same Lua state
Cons:
- requires a modified Lua core (not available as a
module)
- application level locking required
- Lua 5.0 and "before release of 5.1" mentioned (docs
not updated for 5.1)
Sample:
<<
local function flood(output, word)
while 1 do
output:lock()
io.write(word, ", ")
output:unlock()
end
end
local output = thread.newmutex()
thread.newthread(flood, {output, "child"})
flood(output, "parent")
<<
=============
Lua Rings (by Roberto Ierusalimschy & Tomás
Guisasola)
=============
http://www.keplerproject.org/rings/
".. library which provides a way to create new Lua states
from within Lua.
It also offers a simple way to communicate between the
creator (master) and
the created (slave) states."
".. master can execute code in any of its slaves but each
slave only has
access to its master (or its own slaves)."
Rings offers separate Lua states, but no multithreading.
This makes it simple,
but it won't use more than one CPU core. Other differences
include:
- opens all Lua standard libraries for subthreads
(Lanes opens the needed ones)
- marshalls numbers, strings, booleans, userdata
(Lanes marshalls also tables, but not userdata)
- "remotedostring" allows executing code in the
master state
(Lanes does _not_ allow subthreads to
trouble/modify master automatically,
to allow effective sandboxing. The same can be
achieved by sending code
over (send/receive) between the threads, but master
needs to explicitly
do this)
- offers "Stable, a very simple API to manage a
shared table at the master
state"
(Lanes does not offer any shared data mechanisms,
by design. They can be
implemented using queues (send/receive) and a
coroutine at the master
end)
Pros:
- "offers Stable, a very simple API to manage a
shared table at the master
state"
Cons:
- thread contents defined as strings, not Lua source
as such; does not
give syntax check at file parsing, does not allow
syntax highlight
- Lua 5.0 mentioned (will be upcoming for 5.1 -
right?)
Sample:
<<
require"rings"
S = rings.new ()
data = { 12, 13, 14, }
print (S:dostring ([[
aux = {}
for i, v in ipairs (arg) do
table.insert (aux, 1, v)
end
return unpack (aux)]], unpack (data))) -- true, 14, 13,
12
S:close ()
<<
==========================
Helper Threads Toolkit (by Javier Guerra G.)
==========================
http://luaforge.net/projects/helper-threads/
"Provides a consistent framework to write non-blocking C
libraries, with a Lua
interface for starting tasks and managing the Futures,
Queues and Threads."
This seems like a companion of the "occasional threading"
model (see below);
Lua side is kept clear of multithreading, while C side can
be "spawn" off to
do things on the background.
Pros:
- provides an "update" mechanism, allowing the (C)
thread and controlling
Lua to interact during execution of the thread
- ...
Cons:
- thread is "only for C code and it can't touch or
access the Lua state",
in other words there is no Lua-side multithreading
concept (by design)
========================
Occasional threading (by Russ Cox)
========================
http://lua-users.org/lists/lua-l/2006-11/msg00368.html
".. able to have certain C calls run in parallel with the
[Lua] VM, but
otherwise keep the VM single-threaded."
That pretty much says it all.
Pros:
- simple, yet providing for the "occasional" need to
run really multithreaded
- can be made into a loadable module (says the
message)
Cons:
- only for occasional usage, the programming paradigm
is still essentially
singlethreaded (by definition)
- not a real project, just a message on the Lua list
(but a good one!)
=============
Lua Lanes
=============
Lua Lanes takes a loose approach, keeping each created Lua
state completely
separate from the others. Parameters, return values and
globals (optionally)
are passed transparently marshalled (serialized) between
the threads.
Pros:
- regular Lua 5.1 module
- completely separate Lua states, one per thread
- very easy programming model, no application level
locking
- scales well, up to 1000's of threads (and any
number of CPU cores)
- provides priorities (-2..+2) for launched threads
- asynchronous queues between M->S and S->M
- threads are cancellable (with complete cleanup)
- timeouts on all pending operations
- thread contents are given as regular (Master side)
Lua functions;
syntax checked early on, syntax highlighting works
(thread contents
can also be given in separate source files)
- standard libraries opened to the subthreads can be
granually decided
- automatic storage of a cancelled thread's globals,
for "resurrectable"
threads
- serializes calls to 'require', allowing wide
compatibility with existing
modules (and all, with minor changes)
Cons:
- marshalling data exchange may be a bottleneck for
huge amounts, in
which case use of filesystem for the bulk data may
be better
- userdata and functions not marshallable in
send/receive
- no shared access to data (can be implemented on top
of the provided features)
- ...
On Fri, 16 May 2008 16:56:38 +0800
"Pete Kay" <petedao@gmail.com> wrote:
Hi,
I am working on an application that connects to a server
through TCP/IP
socket and listen for events continuously. When a
certain event is picked
up, the application should performance some tasks.
What I want to do is to use Lua socket to listen for the
events and then
create a new thread each time a particular event type is
received.
I found that there are two ways to do it, one is using
coroutine and the
other one is to install Lua Thread.
It seems like they are very similar but I don't quite
understand when it is
better to us coroutine or LuaThread.
Could someone give me some suggestions?
Thanks,
Pete