ltask - A multi tasking library for lua

classic Classic list List threaded Threaded
22 messages Options
12
Reply | Threaded
Open this post in threaded view
|

ltask - A multi tasking library for lua

云风 Cloud Wu
I wrote a new multi tasking library for lua these days, it still work
in process, but I'm pleased to announce here to get more feedback :)

https://github.com/cloudwu/ltask

The core of the library is a m:n schedule , it maps m task (one lua
state per task) to n os thread. (In windows, it uses windows native
threading api, otherwise it uses pthead)

No data can be shared among lua states , the only way for cooperative
is the build-in channels .

ltask has no facility like timer, blocked I/O, etc. but I think it's
easy to use other library (like levent
https://github.com/xjdrew/levent)
on it.

--
http://blog.codingnow.com

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

杨博
Cool!

云风 <[hidden email]>于2015年4月29日星期三写道:
I wrote a new multi tasking library for lua these days, it still work
in process, but I'm pleased to announce here to get more feedback :)

https://github.com/cloudwu/ltask

The core of the library is a m:n schedule , it maps m task (one lua
state per task) to n os thread. (In windows, it uses windows native
threading api, otherwise it uses pthead)

No data can be shared among lua states , the only way for cooperative
is the build-in channels .

ltask has no facility like timer, blocked I/O, etc. but I think it's
easy to use other library (like levent
https://github.com/xjdrew/levent)
on it.

--
http://blog.codingnow.com



--
杨博 (Yang Bo)

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Victor Bombi
In reply to this post by 云风 Cloud Wu
I am a LuaLanes fanatic.
Did you know? : https://github.com/LuaLanes/lanes

----- Original Message -----
From: "??" <[hidden email]>
To: "Lua mailing list" <[hidden email]>
Sent: Wednesday, April 29, 2015 10:46 AM
Subject: ltask - A multi tasking library for lua


>I wrote a new multi tasking library for lua these days, it still work
> in process, but I'm pleased to announce here to get more feedback :)
>
> https://github.com/cloudwu/ltask
>
> The core of the library is a m:n schedule , it maps m task (one lua
> state per task) to n os thread. (In windows, it uses windows native
> threading api, otherwise it uses pthead)
>
> No data can be shared among lua states , the only way for cooperative
> is the build-in channels .
>
> ltask has no facility like timer, blocked I/O, etc. but I think it's
> easy to use other library (like levent
> https://github.com/xjdrew/levent)
> on it.
>
> --
> http://blog.codingnow.com
>

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

云风 Cloud Wu
2015-04-30 15:48 GMT+08:00 Victor Bombi <[hidden email]>:
> I am a LuaLanes fanatic.
> Did you know? : https://github.com/LuaLanes/lanes

I read the description from http://lua-users.org/wiki/MultiTasking before.

The main idea of ltask is a M:N schedule , but the lua lanes is one
lua states per thread . It's the main difference .
So you can create large number tasks (may be  thousands)  in ltask,
the schedule and the message channels may be a little more efficient
:)

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

彭 书呆
在 2015/4/30 16:03, 云风 写道:

> 2015-04-30 15:48 GMT+08:00 Victor Bombi <[hidden email]>:
>> I am a LuaLanes fanatic.
>> Did you know? : https://github.com/LuaLanes/lanes
> I read the description from http://lua-users.org/wiki/MultiTasking before.
>
> The main idea of ltask is a M:N schedule , but the lua lanes is one
> lua states per thread . It's the main difference .
> So you can create large number tasks (may be  thousands)  in ltask,
> the schedule and the message channels may be a little more efficient
> :)
>

I had a glimpse of the code. I like the idea of M:N schedule.

I see the ``select, send, recv`` functions mimics the sockets, but
only in a non-blocking style. is there a plan to add some blocking
synchonization mechanism (e.g. call `yield` inside send or recv)?


I also noticed your packing/unpacking (or serialization/deserialization)
code have limitations on the data structure. I would like it to have support
for, at least, Lua functions with no (explicit) upvalues and tables having
entries refered to same object.
or, maybe you could take use of some existing serialization modules.


one last thought is the single schedule struct might hurt the scalability.
I see read-write lock is used to protect the shared queue.
if this code is to be used in very large parallel systems, I'd suggest some
lock free algorithms.

--
the nerdy Peng / 书呆彭 / Sent from Thunderbird



Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

云风 Cloud Wu
>
> I had a glimpse of the code. I like the idea of M:N schedule.
>
> I see the ``select, send, recv`` functions mimics the sockets, but
> only in a non-blocking style. is there a plan to add some blocking
> synchonization mechanism (e.g. call `yield` inside send or recv)?
>

If select returns nil (no channels can read), it will set the status
of task to BLOCKED,
and the following coroutine.yield() will block.

You can use a few lines of lua  code to  wrap a blocking recv like this :

https://github.com/cloudwu/ltask/blob/master/consumer.lua

function recv()
  while true do
    if ltask.select(c) then
        local ok, value = ltask.recv(c)
        if ok then
            return value
        end
    end
     coroutine.yield()
   end
end

> I also noticed your packing/unpacking (or serialization/deserialization)
> code have limitations on the data structure. I would like it to have support
> for, at least, Lua functions with no (explicit) upvalues and tables having
> entries refered to same object.
> or, maybe you could take use of some existing serialization modules.

You can use your  serialization modules , and send the serialized
string or lightuserdata.

> one last thought is the single schedule struct might hurt the scalability.
> I see read-write lock is used to protect the shared queue.
> if this code is to be used in very large parallel systems, I'd suggest some
> lock free algorithms.

The queue haven't use read-write lock, it uses a simple spin-lock.
I don't think the lock free queue would be better here, but more complex.

--
http://blog.codingnow.com

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Shmuel Zeigerman
On 30/04/2015 14:40, 云风 wrote:

Dear Chinese colleagues!

Could you please put your names (or Internet nick-names) in Latin
letters, to make it possible to those of us not able to read Chinese to
know who the message author is when we look at the field "From"?

--
Shmuel

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Robert Raschke

Dear Shmuel,

I think it's not too much to ask of you to try and read the names as they are. After all, our Chinese colleagues write the text of their emails in English! Everyone should have at least the freedom to have their name appear as they desire.

Regards,
Robby

On Apr 30, 2015 1:22 PM, "Shmuel Zeigerman" <[hidden email]> wrote:
On 30/04/2015 14:40, 云风 wrote:

Dear Chinese colleagues!

Could you please put your names (or Internet nick-names) in Latin letters, to make it possible to those of us not able to read Chinese to know who the message author is when we look at the field "From"?

--
Shmuel

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

云风 Cloud Wu
In reply to this post by Shmuel Zeigerman
> Could you please put your names (or Internet nick-names) in Latin letters,
> to make it possible to those of us not able to read Chinese to know who the
> message author is when we look at the field "From"?

It's the gmail add my chinese name from my google account , I change
it in gmail settings just now, and add my english name after chinese
name .


--
http://blog.codingnow.com

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

彭 书呆
In reply to this post by Shmuel Zeigerman
在 2015/4/30 20:22, Shmuel Zeigerman 写道:
>
> Dear Chinese colleagues!
>
> Could you please put your names (or Internet nick-names) in Latin letters, to make it possible to those of us not able to read Chinese to know who the message author is when we look at the field "From"?
>

I switched from gmail to outlook recently but forgot to reconfigure my email agent. sorry for that.
now you should see my name spelled in Latin letters (the Chinese Pinyin).

--
the nerdy Peng / 书呆彭 / Sent from Thunderbird



Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Shmuel Zeigerman
On 30/04/2015 17:35, Peng Z.C. wrote:
>
> I switched from gmail to outlook recently but forgot to reconfigure my
> email agent. sorry for that.
> now you should see my name spelled in Latin letters (the Chinese Pinyin).
>

Many thanks to all who replied!

--
Shmuel

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Dirk Laurie-2
In reply to this post by Shmuel Zeigerman
Shmuel Zeigerman wrote:

> Dear Chinese colleagues!
>
> Could you please put your names (or Internet nick-names) in Latin letters, to make it
> possible to those of us not able to read Chinese to know who the message author is
> when we look at the field "From"?

I'm not sure that the result is any more enlightening than the original
Chinese — but Google Translate renders the three names thus:

Yun Feng
Yang Bo
Geeks Peng

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

彭 书呆
在 2015/5/1 4:07, Dirk Laurie 写道:

> Shmuel Zeigerman wrote:
>
>> Dear Chinese colleagues!
>>
>> Could you please put your names (or Internet nick-names) in Latin letters, to make it
>> possible to those of us not able to read Chinese to know who the message author is
>> when we look at the field "From"?
> I'm not sure that the result is any more enlightening than the original
> Chinese — but Google Translate renders the three names thus:
>
> Yun Feng
> Yang Bo
> Geeks Peng
>
I think it's not the signature which shows up in the email body but the `FROM` field
of the email headers which would mess up email agent apps. CJK characters are
not only unrecognizable by many people but sometimes unviewable/unprintable
on theirs systems which don't have according fonts installed.

thunderbird always displays `ME` so I didn't realized I have Chinese characters
in the `FROM` header of my email (in utf8 encoding) until Shmuel pointed it out.

--
the nerdy Peng / 书呆彭 / Sent from Thunderbird



Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

David Crayford
In reply to this post by 云风 Cloud Wu
Looks like a nice library but I'll have to give it a miss because of the
unchecked mallocs.

     struct queue *q = malloc(sizeof(*q));
     // malloc never failed
     assert(q);

In my experience malloc does fail and quite often when running on a
system with constrained memory. I see a lot of code with unchecked
mallocs on github
and I don't like it. If it's too much effort to check return values why
not just wrapper malloc/calloc so OOM failures set a message and exit
cleanly? Of course,
it's not just open source code that has this issue. I've raised many
tickets for expensive enterprise software with the same problem.

On 29/04/2015 4:46 PM, 云风 wrote:

> I wrote a new multi tasking library for lua these days, it still work
> in process, but I'm pleased to announce here to get more feedback :)
>
> https://github.com/cloudwu/ltask
>
> The core of the library is a m:n schedule , it maps m task (one lua
> state per task) to n os thread. (In windows, it uses windows native
> threading api, otherwise it uses pthead)
>
> No data can be shared among lua states , the only way for cooperative
> is the build-in channels .
>
> ltask has no facility like timer, blocked I/O, etc. but I think it's
> easy to use other library (like levent
> https://github.com/xjdrew/levent)
> on it.
>


Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

云风 Cloud Wu
> In my experience malloc does fail and quite often when running on a system
> with constrained memory. I see a lot of code with unchecked mallocs on
> github
> and I don't like it. If it's too much effort to check return values why not
> just wrapper malloc/calloc so OOM failures set a message and exit cleanly?

I would like implement the main function first, and then write the
details about these checks.

--
http://blog.codingnow.com

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

David Crayford


On 1/05/2015 9:53 PM, 云风 Cloud Wu wrote:
>> In my experience malloc does fail and quite often when running on a system
>> with constrained memory. I see a lot of code with unchecked mallocs on
>> github
>> and I don't like it. If it's too much effort to check return values why not
>> just wrapper malloc/calloc so OOM failures set a message and exit cleanly?
> I would like implement the main function first, and then write the
> details about these checks.
>
Fair enough. But you'll save a lot of effort debugging your library for
OOM checks with an xmalloc wrapper rather than diagnosing a core dump.
IMO, better to write your code with error checking from the start even
if it's crash-on-failure wrappers which may not cut it for production code.

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

William Ahern
In reply to this post by David Crayford
On Fri, May 01, 2015 at 09:19:36PM +0800, David Crayford wrote:

> Looks like a nice library but I'll have to give it a miss because of the
> unchecked mallocs.
>
>     struct queue *q = malloc(sizeof(*q));
>     // malloc never failed
>     assert(q);
>
> In my experience malloc does fail and quite often when running on a system
> with constrained memory. I see a lot of code with unchecked mallocs on
> github and I don't like it. If it's too much effort to check return values
> why not just wrapper malloc/calloc so OOM failures set a message and exit
> cleanly? Of course, it's not just open source code that has this issue.
> I've raised many tickets for expensive enterprise software with the same
> problem.

I've been following the development of Rust recently. One of the
disconcerting issues I recently discovered is that the Rust standard
libraries exit the process on malloc failure. I think that's really
unfortunate. There are many common scenarios (e.g. network daemons) where
recovering from malloc failure is comparatively easy and very much
advisable, at least if you use the appropriate patterns from the beginning
of development. It would be ludicrous to disconnect thousands of clients
just because 1 client request triggered resource exhaustion.

I realize it's a difficult problem to solve for them. Like Lua, Rust depends
on many hidden dynamic allocations. But Rust doesn't have exceptions, and
the try! and unwrap patterns were only recently settled upon as best
practice.

Yet for a so-called systems language it's a huge negative to exit on
allocation failure. Even Lua doesn't abort the process (notwithstanding the
default panic handler). Rather, the VM remains in a consistent state.

I suppose we can't hold every project to the high standards that Lua
maintains :) Still, if a project doesn't aspire to high standards, quality
will likely be uniformly poor.

Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

Tim Hill

>> In my experience malloc does fail and quite often when running on a system
>> with constrained memory. I see a lot of code with unchecked mallocs on
>> github and I don't like it. If it's too much effort to check return values
>> why not just wrapper malloc/calloc so OOM failures set a message and exit
>> cleanly? Of course, it's not just open source code that has this issue.
>> I've raised many tickets for expensive enterprise software with the same
>> problem.
>
> I've been following the development of Rust recently. One of the
> disconcerting issues I recently discovered is that the Rust standard
> libraries exit the process on malloc failure. I think that's really
> unfortunate. There are many common scenarios (e.g. network daemons) where
> recovering from malloc failure is comparatively easy and very much
> advisable, at least if you use the appropriate patterns from the beginning
> of development. It would be ludicrous to disconnect thousands of clients
> just because 1 client request triggered resource exhaustion.
>
> I realize it's a difficult problem to solve for them. Like Lua, Rust depends
> on many hidden dynamic allocations. But Rust doesn't have exceptions, and
> the try! and unwrap patterns were only recently settled upon as best
> practice.
>

It’s actually a *very* hard problem to solve in large blocks of C code. Typically there are many hidden allocations even within the CRT (even printf() frequently does this), and once you get one failure handling this cleanly without a cascade is exceedingly tricky. In some of our systems we shim malloc() and it’s variants, and then pre-allocate a “reserve tank” of memory. If an allocation fails we release the “reserve tank” back to the heap and retry the allocation. However, even in this case we initiate a clean shutdown, since if you are in this high-stress condition that’s pretty much all you can hope for.

In the case of Rust and large server systems, the assumption (which I think is reasonable) is that the server is running on a virtual memory OS with significant physical resources. In this case, running out of memory is a severe condition and bailing is a reasonable response. After all, why did it run out of memory? On a large system, in all probability, it’s a memory leak and there is no way to get around that EXCEPT by a restart (and, of course, trying to fix the leak).

—Tim



Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

William Ahern
In reply to this post by 云风 Cloud Wu
On Fri, May 01, 2015 at 09:53:57PM +0800, ???? Cloud Wu wrote:
> > In my experience malloc does fail and quite often when running on a system
> > with constrained memory. I see a lot of code with unchecked mallocs on
> > github
> > and I don't like it. If it's too much effort to check return values why not
> > just wrapper malloc/calloc so OOM failures set a message and exit cleanly?
>
> I would like implement the main function first, and then write the
> details about these checks.
>

Handling allocation failure isn't a detail. Adding that later will be much
more bug prone because proper handling often depends on the details of how
you maintain data structure consistency. There can be hidden dependencies
that you'll forget about later, leaving dangling pointers, inconsistent
locks, and other nastiness.

In the context of Lua it's even more important. Almost any call into Lua
could trigger an exception. Anytime you call into Lua, all your C data
structures should be in a safe state--initialized and anchored in the Lua VM
object graph (to prevent leaks). That requires careful ordering of your C
statements. For example, this code is wrong

        FOO *foo = NULL, **fp;
        int error;

        foo = foo_create(&error);
        if (!foo)
                goto error;
        fp = lua_newuserdata(L, sizeof *fp);
        *fp = foo;
        luaL_setmetatable(L, "FOO*");

because lua_newuserdata could throw an exception, causing your foo object to
leak. Or luaL_setmetatable could throw before attaching the proper __gc
handler to the userdata object, also causing a leak. Better code does

        fp = lua_newserdata(L, sizeof *fp);
        *fp = NULL; /* __gc should handle NULL properly */
        luaL_setmetatable(L, "FOO*");
        *fp = foo_create(&error);
        if (!*fp)
                goto error;

IMHO, decide now: implement state unwinding, or make it policy going forward
that OOM is not something you'll ever handle. Putting it off is the worst
choice of all.


Reply | Threaded
Open this post in threaded view
|

Re: ltask - A multi tasking library for lua

William Ahern
In reply to this post by Tim Hill
On Fri, May 01, 2015 at 12:45:50PM -0700, Tim Hill wrote:

>
> >> In my experience malloc does fail and quite often when running on a system
> >> with constrained memory. I see a lot of code with unchecked mallocs on
> >> github and I don't like it. If it's too much effort to check return values
> >> why not just wrapper malloc/calloc so OOM failures set a message and exit
> >> cleanly? Of course, it's not just open source code that has this issue.
> >> I've raised many tickets for expensive enterprise software with the same
> >> problem.
> >
> > I've been following the development of Rust recently. One of the
> > disconcerting issues I recently discovered is that the Rust standard
> > libraries exit the process on malloc failure. I think that's really
> > unfortunate. There are many common scenarios (e.g. network daemons) where
> > recovering from malloc failure is comparatively easy and very much
> > advisable, at least if you use the appropriate patterns from the beginning
> > of development. It would be ludicrous to disconnect thousands of clients
> > just because 1 client request triggered resource exhaustion.
> >
> > I realize it's a difficult problem to solve for them. Like Lua, Rust depends
> > on many hidden dynamic allocations. But Rust doesn't have exceptions, and
> > the try! and unwrap patterns were only recently settled upon as best
> > practice.
> >
>
> It???s actually a *very* hard problem to solve in large blocks of C code.
> Typically there are many hidden allocations even within the CRT (even
> printf() frequently does this) and once you get one failure handling this
> cleanly without a cascade is exceedingly tricky.

Yes, printf has many different points of failure internally. But from the
caller's perspective you only need to check a single return value. (I would
also note that glibc is unique in that the underlying formatting code
heavily uses dynamic allocation. Most implementations only use dynamic
allocation for formatting doubles, or not at all. Which means of all the
errors printf handles, OOM is least problematic. As it can be in many cases.
When you try to handle memory failure correctly rather than disregarding it,
you tend to make decisions which ease the burden and which often improve
overall code quality. And in any event, glibc printf and snprintf does
handle OOM, because as a library interface that's expected and should be
expected!)

IME, if you follow RAII principles, it's not hard (difficult, complex) at
all. Rather, it's _tedious_. But those are entirely separate qualities.
Tedium is part-and-parcel of writing correct C code. Avoiding the necessary
tedium when working in C is one reason to integrate tools like Lua, where
the language constructs strike a different balance, especially wrt to
resource management.

RAII isn't just a set of stylistic idioms for C++. It's about aggregating
resource acquisition into a smaller number of localized code blocks. That
reduces the burden of error checking, and ensures that there are fewer
places where your program can be an inconsistent state. The benefit is
compounded when you adhere to the principle at all layers, so that the paths
where errors bubble up through call chains are also reduced.

You can apply the principle in any language, including C, and whether or not
your code is heavily object oriented.

> In some of our systems we shim malloc() and it???s variants, and then
> pre-allocate a ???reserve tank??? of memory. If an allocation fails we
> release the ???reserve tank??? back to the heap and retry the allocation.
> However, even in this case we initiate a clean shutdown, since if you are
> in this high-stress condition that???s pretty much all you can hope for.
>
> In the case of Rust and large server systems, the assumption (which I
> think is reasonable) is that the server is running on a virtual memory OS
> with significant physical resources. In this case, running out of memory
> is a severe condition and bailing is a reasonable response. After all, why
> did it run out of memory? On a large system, in all probability, it???s a
> memory leak and there is no way to get around that EXCEPT by a restart
> (and, of course, trying to fix the leak).

IME those are not very good assumptions. Memory leaks are not very high on
my list of culprits when it comes to resource exhaustion, including memory
exhaustion. If you rigorously adhere to disciplines like single owner (a
foundational assumption of Rust, BTW), then you avoid the kind of complex
code that favors memory leaks. Copy-by-value and immutability are similar
strategies (the latter also heavily adopted by Rust).

Your assumptions may very well hold true in your environments. I just think
it's wrong to assume that the environments you work in are as common as you
think, even _if_ they're the most common universally. (Which, for the sake
of argument, I'll grant you.)

12