From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 13:06:39
|
Hi there! There is this tiny sexy little thing on www.lua.org. Did you guys have any close(r) encounters? Should I invest some more time/effort in that direction? Rationale is to have simpler and lower-weight script machine than what we have now. Also, threadingwise they claim to be able to make a shared/perthread state that would simplify lots of things (no need to introspect/clone interps and such). All resulting in a smaller footprint and faster execution. I know we all use/love Tcl (we depend on it existentially) but it mostly pays off being flexible and open minded. I also know that we cannot refactor server to exclude Tcl altogether (as we depend on the cross-platform API that libtcl provides)... Still... do not crucify me immediately and tag me as a heretic! If anybody had any experience, being good or bad I'd love to hear them. My first experience: download 5.1.3 Lua to my powerbook in 3 seconds, compile in 5 and I'm up and running :-) It is really lightweight! I yet have to see whhat is missing and what needs to be done by ourselves (most probably IO will be missing I guess; RE's as well). Zoran |
From: Andrew P. <at...@pi...> - 2008-05-09 13:33:37
|
On Fri, May 09, 2008 at 03:05:56PM +0200, Vasiljevic Zoran wrote: > There is this tiny sexy little thing on www.lua.org. > Did you guys have any close(r) encounters? > Should I invest some more time/effort in that direction? I don't know, but it would be interesting! Talk to Jean-Claude Wippler, he started using Lua for the core engine of Vlerq earlier this year. (And of course he is already a Tcl expert, not to mention other languages.) You might also want to check with Lua people to see what they're currently doing for web and application servers. I wonder if/how they leverage coroutines in interesting ways. Perhaps they'd be interested in Naviserver with Lua, I don't know. I've never used it for anything at all, but Lua is high on my list of Interesting Programming Languages. > It is really lightweight! I yet have to see whhat is missing > and what needs to be done by ourselves (most probably IO > will be missing I guess; RE's as well). Lua reportedly has regular expression suppot, it's just not included in core Lua, you have to load a third party extension module. That should be just fine (even superior) as a design, but Lua seems to be crying out for a real Batteries Included distribution, with good standard libraries, etc. -- Andrew Piskorski <at...@pi...> http://www.piskorski.com/ |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 14:01:58
|
On 09.05.2008, at 15:32, Andrew Piskorski wrote: > > Talk to Jean-Claude Wippler, he started using Lua for the core engine > of Vlerq earlier this year. (And of course he is already a Tcl > expert, not to mention other languages.) Yep! I know the guy. Good tip. I will contact him these days. > > > You might also want to check with Lua people to see what they're > currently doing for web and application servers. I wonder if/how they > leverage coroutines in interesting ways. Perhaps they'd be interested > in Naviserver with Lua, I don't know. Me neither. But what I would like to see is how they do concurrent programmig i.e. how they support multiple threads of execution. Tcl compartment model is fine for some case but it presents a real pain in the neck when you have a large initial state that needs to be replicated in each and every thread. This bugs us for years and I attempted to solve that, but w/o nice and generic solution. > > >> It is really lightweight! I yet have to see whhat is missing >> and what needs to be done by ourselves (most probably IO >> will be missing I guess; RE's as well). > > Lua reportedly has regular expression suppot, it's just not included > in core Lua, you have to load a third party extension module. That > should be just fine (even superior) as a design, but Lua seems to be > crying out for a real Batteries Included distribution, with good > standard libraries, etc. Unicode is also an issue... btw. I must go shopping arround for some days to get a clear picture. It is still relatively unclear to me except for the first couple of steps that were really promising. IMO, it pays of to look deeper. JCW is a good tip! I'll talk to the guy. Cheers Zoran |
From: Vlad S. <vl...@cr...> - 2008-05-09 15:05:39
|
There is nothing wrong with it, actually it could be valuable to Lua users. I think it might be same as with PHP module, it gives flexibility to use either scripting language or both for development. But Tcl still is the core language and server will always be linked to Tcl library. And we still have problem with Tcl initialization. Vasiljevic Zoran wrote: > Hi there! > > There is this tiny sexy little thing on www.lua.org. > Did you guys have any close(r) encounters? > Should I invest some more time/effort in that direction? > Rationale is to have simpler and lower-weight script > machine than what we have now. Also, threadingwise they > claim to be able to make a shared/perthread state that > would simplify lots of things (no need to introspect/clone > interps and such). All resulting in a smaller footprint > and faster execution. > > I know we all use/love Tcl (we depend on it existentially) > but it mostly pays off being flexible and open minded. > I also know that we cannot refactor server to exclude Tcl > altogether (as we depend on the cross-platform API that > libtcl provides)... > Still... do not crucify me immediately and tag me as a > heretic! If anybody had any experience, being good or > bad I'd love to hear them. > > My first experience: download 5.1.3 Lua to my powerbook > in 3 seconds, compile in 5 and I'm up and running :-) > It is really lightweight! I yet have to see whhat is missing > and what needs to be done by ourselves (most probably IO > will be missing I guess; RE's as well). > > Zoran > > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Don't miss this year's exciting event. There's still time to save $100. > Use priority code J8TL2D2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel > |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 15:39:36
|
On 09.05.2008, at 17:04, Vlad Seryakov wrote: > But Tcl still is the core language and server will always be linked to > Tcl library. And we still have problem with Tcl initialization. Damn, I know that! This bugs us for about 8 years _constantly_. The cost of a fully loaded interp is outrageous. Recently we launched internal development of the module being able to handle 1000+ "users" (in our product-terms, workstations) with a stock 4 GB memory off-the-shelf machine like xserve or a Mac Pro. If we'd to make a thread-per-workstation, we'd need 1000 * at_least_10MB of virtual memory! No go. So I had to write all in plain C. This of course limited the functionality as we had to drop lots of it to buy time :-( What Tcl really lacks is a per-thread and global state. And I see _no_way_ how this can be made... Grmpf. I saw somewhere that Lua can have global and per-thread state and that you can provide your own locking primitives they use to lock their own code, but I haven't dig deeper there... I think I will make it a weekend project. Cheers Zoran |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 16:06:46
|
On 09.05.2008, at 17:38, Vasiljevic Zoran wrote: > I saw somewhere that Lua can have global and per-thread state > and that you can provide your own locking primitives they use > to lock their own code, but I haven't dig deeper there... Damn again. This is a global lock that serializes everything. A no go :-( Same applies to others (Ruby, Phyton, Perl). FWIW, seems like there isn't a script language which can handle MT well. Must we write a new language? I knew it... We are always re-inventing the wheel; over and over again. I see that I must dig even deeper that I thought initially... |
From: Vlad S. <vl...@cr...> - 2008-05-09 17:44:35
|
Can you explain me about this global-state, please. and, do why do you need all separate 1000 threads for every user, is the requirement to be connected to all at the same time? just wondering Vasiljevic Zoran wrote: > On 09.05.2008, at 17:38, Vasiljevic Zoran wrote: > >> I saw somewhere that Lua can have global and per-thread state >> and that you can provide your own locking primitives they use >> to lock their own code, but I haven't dig deeper there... > > Damn again. This is a global lock that serializes everything. > A no go :-( > Same applies to others (Ruby, Phyton, Perl). > > FWIW, seems like there isn't a script language which can handle > MT well. Must we write a new language? I knew it... We are > always re-inventing the wheel; over and over again. > > I see that I must dig even deeper that I thought initially... > > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Don't miss this year's exciting event. There's still time to save $100. > Use priority code J8TL2D2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel > |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 17:54:10
|
On 09.05.2008, at 19:44, Vlad Seryakov wrote: > Can you explain me about this global-state, please. > Ideally, one would have all stuff that is needed loaded once. Stuff that is local to thread is handled locally (procedures, vars that that one thread creates). OTOH, the whole "knowledge" about the application is loaded and held once. Effectively, what I need is a upside-down of the Tcl model: one interp any many threads. Don't tell me: go shop Java. This does not compute (for various unrelated reasons). > and, do why do you need all separate 1000 threads for every user, is > the > requirement to be connected to all at the same time? just wondering Yes. 1000's of workstations may be connected all the time and over a long time. And all of them are pumping data to the server, mostly. Doing this in a event-loop mode is possible but not feasible. I must isolate everybody in a thread because of the potential (complex) state that each connection may have. |
From: Vlad S. <vl...@cr...> - 2008-05-09 18:01:11
|
> Effectively, what I need is a upside-down of the > Tcl model: one interp any many threads. > Don't tell me: go shop Java. This does not compute > (for various unrelated reasons). You can use ns_job, you define how may Tcl interp/threads you may use and then just submit tasks, each task will get state and do the work. I guess you already explored that. >> and, do why do you need all separate 1000 threads for every user, is >> the >> requirement to be connected to all at the same time? just wondering > > Yes. 1000's of workstations may be connected all the time > and over a long time. And all of them are pumping data to > the server, mostly. Doing this in a event-loop mode is > possible but not feasible. I must isolate everybody in a > thread because of the potential (complex) state that each > connection may have. You may combine methods, like let one thread to handle several connections sequentially if that will work but i do not have exact details so i will stop now. |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 18:18:10
|
On 09.05.2008, at 20:00, Vlad Seryakov wrote: >> Effectively, what I need is a upside-down of the >> Tcl model: one interp any many threads. >> Don't tell me: go shop Java. This does not compute >> (for various unrelated reasons). > > You can use ns_job, you define how may Tcl interp/threads you may use > and then just submit tasks, each task will get state and do the work. > > > I guess you already explored that. Yes. Won't work. I mean it _could_ but I need to program for that _extra_. Ideally, I would start 10,100,1000 threads each with its own small "universe" that actually contains just dark matter (nothing) whereas all the good-stuff is located centraly (a large mother-interpreter?). Ideally, all the Tcl commands would be automagically executed "in the mother" but have access to my "local" space (for uplevel and upvar and friends). > > You may combine methods, like let one thread to handle several > connections sequentially if that will work but i do not have exact > details so i will stop now. You can of course design a 1001 model that will work for the particular case. What I need is a _generic_ scalable model that will work always. Imagine a Tcl interp that costs nothing to create and consumes just 5-10 KB virtual memory! Yet it has "access" to (or "behaves" like) a full-blown beast that sourced thousand+ files and loaded hundred+ extensions... The blues that we are against is that we must source 1000s and load 100s of things for each and every connection thread. Given connection times are short, and one re-uses conn threads all computes well. BUT.. in my case, connection times are long (hours, days)... So, upside down. Hence a new methodology is needed. I tried to reduce it to event-loop type, but this is entirely different programing technique and will not work with the code we already have. I will have to digest this alone. If anything _generic_ comes out of that I will give it away. But it is good at least to express the idea here, in case somebody has some magic already done up his sleeve :-) Cheers Zoran |
From: Vlad S. <vl...@cr...> - 2008-05-09 18:29:22
|
> > Yes. Won't work. I mean it _could_ but I need to program > for that _extra_. Ideally, I would start 10,100,1000 threads > each with its own small "universe" that actually contains > just dark matter (nothing) whereas all the good-stuff is > located centraly (a large mother-interpreter?). > Ideally, all the Tcl commands would be automagically executed > "in the mother" but have access to my "local" space (for > uplevel and upvar and friends). So what you need is the ability to create "lightweight" Tcl thread with minimum commands, but with couple "important" commands to access special "global state" or ability to submit/retrieve data from "global state". Is this correct? But that "monster" thread, how do you execute in it? Using ns_proxy or messaging, or some other way? I guess you create regular pthread, call Tcl_CreateInterp, register several command and execute your Tcl script. Why do you think it is not generic enough? |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-09 18:44:15
|
On 09.05.2008, at 20:29, Vlad Seryakov wrote: > So what you need is the ability to create "lightweight" Tcl thread > with > minimum commands, but with couple "important" commands to access > special > "global state" or ability to submit/retrieve data from "global state". > Is this correct? Yes. The lightweight state should be light (a wonder!) in terms it is private, easily created, easily destroyed and small in memory footprint. The closest "thing" in the Tcl universe would be a child interp ([interp create]). > > > But that "monster" thread, how do you execute in it? > Using ns_proxy or messaging, or some other way? Well messaging is first that comes to mind. Threading extension already does that. The gotcha's are mostly upvars and uplevels :-( > > > I guess you create regular pthread, call Tcl_CreateInterp, > register several command and execute your Tcl script. > Why do you think it is not generic enough? Well, kind of :-) It is like: I guess you go sit in the rocket, turn on the boosters and fly to moon! Nothing simpler that that. Unfortunately. I'm not NASA! Our app consist of roghly 350.000 lines of Tcl code and loads about 20+ external modules, all containing internal state. The command set is 500+ top-level commands and they all depend on the internal state. What MIGHT work is kind of this: create some numbers of fully loaded interps, each sitting in its own thread. A compute-farm, so to say. Then every other thread just creates a slave interp in one of those and runs all its scripts in his private slave in one of those parked threads in the compute-farm, using some kind of message passing. The slaves have all the commands aliased into the main one. Not sure what would happen with uplevels and upvars here (need to think) but this is roughly what I'm contemplating about now. So when a thread exits, its thin-slave is just deleted completely. And created it is also fast. Just alias all commands from the master. Not sure about the global variables... this is still open. |
From: Andrew P. <at...@pi...> - 2008-05-10 04:13:26
|
On Fri, May 09, 2008 at 06:06:05PM +0200, Vasiljevic Zoran wrote: > > I saw somewhere that Lua can have global and per-thread state > > and that you can provide your own locking primitives they use > > to lock their own code, but I haven't dig deeper there... > > Damn again. This is a global lock that serializes everything. > A no go :-( > Same applies to others (Ruby, Phyton, Perl). Zoran, are you SURE? Because from what I've read about Lua, it does NOT have any sort of single global lock limiting true parallelism to one cpu/core at a time the way Python and Ruby do. Lua's default behavior is coroutines cooperatively multitasking on just a single cpu, but AFAIK the Lua implementation is not inherently limited to that. Your application clearly wants to use many thousands of stateful lightweight processes. AFAIK Lua and especially Erlang both support that out of the box. Do you ALSO need to run 2 or 8 or more of those threads in parallel (at the exact same time) on a single multi-cpu server? Recent versions of Erlang definitely support that. I'm not sure whether or not Lua supports that out of the box, but it may be feasible to make it work. (Erlang's message passing design should also mean that you can easily start running stuff across two or more independent server boxes too. Lua has no equilvalent, AFAIK, although there must be people in the Lua community thinking about that sort of stuff.) -- Andrew Piskorski <at...@pi...> http://www.piskorski.com/ |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-10 09:09:25
|
On 10.05.2008, at 06:13, Andrew Piskorski wrote: > On Fri, May 09, 2008 at 06:06:05PM +0200, Vasiljevic Zoran wrote: > >>> I saw somewhere that Lua can have global and per-thread state >>> and that you can provide your own locking primitives they use >>> to lock their own code, but I haven't dig deeper there... >> >> Damn again. This is a global lock that serializes everything. >> A no go :-( >> Same applies to others (Ruby, Phyton, Perl). > > Zoran, are you SURE? Because from what I've read about Lua, it does > NOT have any sort of single global lock limiting true parallelism to > one cpu/core at a time the way Python and Ruby do. Lua's default > behavior is coroutines cooperatively multitasking on just a single > cpu, but AFAIK the Lua implementation is not inherently limited to > that. Coroutines are something similar, (purists outthere, note: _similar_) to Tcl event loop in terms that they work on a single processor. This is not real MP multithreading that we need in order to scale. From the programing perspective, they are indeed very interesting because they don't force me into the "event-loop" shoe. I have nothing against event-loop. It is just that it is really targeted to a GUI type of apps. I was greping to "lua_lock" calls arround the code and found mostly: something () { lua_lock(L); //... lua_unlock(L); } OK, this must _not_ mean they are absolutely serialized, but it really appears to me like that on the first glance. What I plan to do is go to Lua developers and ask couple of questions... > > > Your application clearly wants to use many thousands of stateful > lightweight processes. AFAIK Lua and especially Erlang both support > that out of the box. Do you ALSO need to run 2 or 8 or more of those > threads in parallel (at the exact same time) on a single multi-cpu > server? Recent versions of Erlang definitely support that. I'm not > sure whether or not Lua supports that out of the box, but it may be > feasible to make it work. Yep, Erlang is something that looks very good as well. I just stumbled across that yesterday. Clever, clever... still I have to see how they works internally and what are the gotchas of their message-passing. Cheers Zoran |
From: Vlad S. <vl...@cr...> - 2008-05-10 16:30:30
|
You may also check out SpiderMonkey javascript. It is thread safe and runtime is not very big. Vasiljevic Zoran wrote: > On 10.05.2008, at 06:13, Andrew Piskorski wrote: > >> On Fri, May 09, 2008 at 06:06:05PM +0200, Vasiljevic Zoran wrote: >> >>>> I saw somewhere that Lua can have global and per-thread state >>>> and that you can provide your own locking primitives they use >>>> to lock their own code, but I haven't dig deeper there... >>> Damn again. This is a global lock that serializes everything. >>> A no go :-( >>> Same applies to others (Ruby, Phyton, Perl). >> Zoran, are you SURE? Because from what I've read about Lua, it does >> NOT have any sort of single global lock limiting true parallelism to >> one cpu/core at a time the way Python and Ruby do. Lua's default >> behavior is coroutines cooperatively multitasking on just a single >> cpu, but AFAIK the Lua implementation is not inherently limited to >> that. > > Coroutines are something similar, (purists outthere, note: _similar_) > to Tcl event loop in terms that they work on a single processor. > This is not real MP multithreading that we need in order to scale. > From the programing perspective, they are indeed very interesting > because they don't force me into the "event-loop" shoe. I have > nothing against event-loop. It is just that it is really targeted to > a GUI type of apps. > I was greping to "lua_lock" calls arround the code and found mostly: > > something () { > lua_lock(L); > //... > lua_unlock(L); > } > > OK, this must _not_ mean they are absolutely serialized, but it > really appears to me like that on the first glance. > What I plan to do is go to Lua developers and ask couple of > questions... > >> >> Your application clearly wants to use many thousands of stateful >> lightweight processes. AFAIK Lua and especially Erlang both support >> that out of the box. Do you ALSO need to run 2 or 8 or more of those >> threads in parallel (at the exact same time) on a single multi-cpu >> server? Recent versions of Erlang definitely support that. I'm not >> sure whether or not Lua supports that out of the box, but it may be >> feasible to make it work. > > Yep, Erlang is something that looks very good as well. I just stumbled > across that yesterday. Clever, clever... still I have to see how > they works internally and what are the gotchas of their message-passing. > > Cheers > Zoran > > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Don't miss this year's exciting event. There's still time to save $100. > Use priority code J8TL2D2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel > -- Vlad Seryakov vl...@cr... http://www.crystalballinc.com/vlad/ |
From: Andrew P. <at...@pi...> - 2008-05-10 04:22:55
|
On Fri, May 09, 2008 at 05:38:38PM +0200, Vasiljevic Zoran wrote: > Recently we launched internal development of the module being > able to handle 1000+ "users" (in our product-terms, workstations) > with a stock 4 GB memory off-the-shelf machine like xserve or > a Mac Pro. If we'd to make a thread-per-workstation, we'd need > 1000 * at_least_10MB of virtual memory! > What Tcl really lacks is a per-thread and global state. > And I see _no_way_ how this can be made... Grmpf. So you probably have 10 MB or so of proc definitions, which are 95+% or even 100% identical in every thread, but Tcl keeps a completely separate 10 MB copy in each and every thread. What you really want is to just have a single read-only 10 MB copy of all those Tcl proc definitions, and have all 1000 otherwise completely independent Tcl interps use those same procs. Zoran, have you talked to Jeff Hobbs about this? He has mentioned possibly adding "interp cloning" and other sorts of related stuff on the AOLserver list before. I understand that the compiled Tcl byte code is somehow specific to the interpretor where it was compiled, so it doesn't (currently) work to somehow have just one copy that you use from multiple interps in multiple threads. But perhaps there's some good way to improve that... -- Andrew Piskorski <at...@pi...> http://www.piskorski.com/ |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-10 13:28:01
|
On 09.05.2008, at 20:44, Vasiljevic Zoran wrote: > What MIGHT work is kind of this: create some numbers of > fully loaded interps, each sitting in its own thread. > A compute-farm, so to say. Then every other thread just > creates a slave interp in one of those and runs all its > scripts in his private slave in one of those parked threads > in the compute-farm, using some kind of message passing. > The slaves have all the commands aliased into the main > one. Not sure what would happen with uplevels and upvars > here (need to think) but this is roughly what I'm > contemplating about now. Upvars/Uplevels will not work. No way. > So when a thread exits, its > thin-slave is just deleted completely. And created it is > also fast. Just alias all commands from the master. Not > sure about the global variables... this is still open. No access to variables... So: no generic solution as I was looking after. FWIW... For those interested: on a Mac PB, using Tcl8.4 and current threading extension, I can load 1000 threads with virgin interp and this costs me about 700MB virtual memory. Dont know about the thread stacks, if I reduce the default, perhaps it will be less (platform specific anyway). But this is acceptable footprint. After all there are 1000 units of execution! If I now just blindly override the [::unknown] command in each of them and go look in a round-robin fashion for a idle "mother" interp (one loaded with all that fancy app state) and execute the "real" command there, instead in my tiny little per-user thread, then this could work fine. Admitently, this is _similar_ to [ns_job] or [therad::send] but it is more "implicit" in the sense that you need not program with [ns_job] of [thread] Tcl API. One can just simply program in plain Tcl, provided the application allows following limitations: no upvars no uplevels no direct variable access no references (channel handles, or other types of handles) Just plain command dispatching. The command may only return things "per-value" (lists, scalars) i.e. something that can be cheaply converted to string. References/hndles are not allowed. Those limitation are actually not bad: they force the programmer to encapsulate the app logic within manageable self-contained blocks. So, at the end... the only "trick" is to create a virgin interp, overload the [::unknown] command and re-route the execution to a farm of pre-parked and loaded interps using in-memory message-passing. Those are all created "equal" and can be created and destroyed on as-needed basis i.e. dynamically (actually, the Naviserver already provides this in form of ns_job and threading extension in form of thread-pools). I will give this a second thought... If this holds water I will see if I can do this in a reasonably generic fashion for general (purpose) usage. Cheers Zoran |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-10 15:50:46
|
On 10.05.2008, at 06:23, Andrew Piskorski wrote: > So you probably have 10 MB or so of proc definitions, which are 95+% > or even 100% identical in every thread, but Tcl keeps a completely > separate 10 MB copy in each and every thread. What you really want is > to just have a single read-only 10 MB copy of all those Tcl proc > definitions, and have all 1000 otherwise completely independent Tcl > interps use those same procs. _RIGHTO_ > > > Zoran, have you talked to Jeff Hobbs about this? He has mentioned > possibly adding "interp cloning" and other sorts of related stuff on > the AOLserver list before. I understand that the compiled Tcl byte > code is somehow specific to the interpretor where it was compiled, so > it doesn't (currently) work to somehow have just one copy that you use > from multiple interps in multiple threads. But perhaps there's some > good way to improve that... No go. I know about that work already. It was done I believe for Cisco as contract-work and is living in Tcl CVS under some branch. The problem is: this is just the single-thread interp-clone. Nothing that can be shared. Since some years I've been trying various approaches how to tackle this problem but I really found no realy good and universal way. I believe there isn't one, after all those years. I will try just this one more idea with unknown-overloading and dispatching unknown command to a battery of preloaded interps living in different threads. Although not 100% transparent (people must code with couple of assumptions) I think it is the most one can do with Tcl. And, I do not think this will improve over time. Hopefully I will soon find piece of mind with this issue and stop going on other people's nervers and saturate email lists :-) Thanks for following so far! Cheers Zoran |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-10 16:08:43
|
On 10.05.2008, at 17:50, Vasiljevic Zoran wrote: > I think > it is the most one can do with Tcl. Hm ... not that bad consider the trivialiy of the example. package req Thread set tp [tpool::create -initcmd { proc sayhello args { return hello-[thread::id] } }] proc unknown args { global tp set id [tpool::post $tp $args] tpool::wait $tp $id tpool::get $tp $id } % time {sayhello} 100 48 microseconds per iteration % sayhello hello-tid0xb0103000 % thread::id tid0xa0111fa0 As you see, unknown triggers the sayhello that is declared on pool threads, but not in my thread. And the execution time is not really bad. And this is just generic stuff. Done in C really tight, I can go make that 1/5 most probably. |
From: Vlad S. <vl...@cr...> - 2008-05-10 16:19:09
|
What will happen if 100 threads will send commands at the same time and those commands will be more complicated, not just return? Main thread will serialize them, i guess. Does not it seems like global lock in Lua? Will it scale the way you want it to scale? Vasiljevic Zoran wrote: > On 10.05.2008, at 17:50, Vasiljevic Zoran wrote: > >> I think >> it is the most one can do with Tcl. > > > Hm ... not that bad consider the > trivialiy of the example. > > package req Thread > set tp [tpool::create -initcmd { > proc sayhello args { > return hello-[thread::id] > } > }] > > proc unknown args { > global tp > set id [tpool::post $tp $args] > tpool::wait $tp $id > tpool::get $tp $id > } > > % time {sayhello} 100 > 48 microseconds per iteration > % sayhello > hello-tid0xb0103000 > % thread::id > tid0xa0111fa0 > > As you see, unknown triggers the sayhello that is declared > on pool threads, but not in my thread. And the execution > time is not really bad. And this is just generic stuff. > Done in C really tight, I can go make that 1/5 most probably. > > > > > ------------------------------------------------------------------------- > This SF.net email is sponsored by the 2008 JavaOne(SM) Conference > Don't miss this year's exciting event. There's still time to save $100. > Use priority code J8TL2D2. > http://ad.doubleclick.net/clk;198757673;13503038;p?http://java.sun.com/javaone > _______________________________________________ > naviserver-devel mailing list > nav...@li... > https://lists.sourceforge.net/lists/listinfo/naviserver-devel > -- Vlad Seryakov vl...@cr... http://www.crystalballinc.com/vlad/ |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-10 16:40:57
|
On 10.05.2008, at 18:15, Vlad Seryakov wrote: > What will happen if 100 threads will send commands at the same time > and > those commands will be more complicated, not just return? > > Main thread will serialize them, i guess. > Does not it seems like global lock in Lua? > Will it scale the way you want it to scale? I believe it will. It is all compromise and it sacrifies speed for memory, obviously. But you could decide how much memory you burn and how fast the system is by tuning the number of workers. At the moment we cannot tune much. All our interps are created equal and all are fully loaded. I would create a number of those heavy interps upfront and make "connection" threads as lightweight as possible (just basic Tcl commands plus ns_ commands). I would instrument the unknown command in them so all that gets executed in the connection thread, gets really excuted in one of those pre-started things, unless it is the ns_ or regular Tcl command. This requires certain conventions in the app but it would I believe scale very well. |
From: Andrew P. <at...@pi...> - 2008-05-10 22:40:02
|
On Sat, May 10, 2008 at 05:50:42PM +0200, Vasiljevic Zoran wrote: > Since some years I've been trying various approaches how to tackle > this problem but I really found no realy good and universal way. > I believe there isn't one, after all those years. I will try just this No, I believe that there certainly must be a good solution to your sort of problem. Whether there's any nice incremental solution in your case is much less clear! E.g., "Rewrite your entire app in Erlang." is probably not a useful solution for you, and would have its own very substantial risks and uncertainties. I certainly encourage you to continue picking the brains of the folks who have serious deep knowledge of the Tcl interpretor's design and implementation. (E.g., I certainly don't understand WHY the Tcl compiled bytecode is somehow magically linked to and usable only by the interp that created it. Why can't you have a single memory region with bytecode used by all 1000 independent interps?) > one more idea with unknown-overloading and dispatching unknown command > to a battery of preloaded interps living in different threads. Although Yes, avoiding having an entire heavyweight Tcl thread + interp for each one of your thousands of client connections is probably the way to go in your case. You're going for some sort of threadpool design instead. But, it IS rather ugly that memory usage from 1000 redundant copies of identical code FORCES you down that road. > Hopefully I will soon find piece of mind with this issue and stop > going on other people's nervers and saturate email lists :-) Not at all, I think you are tackling an inherently interesting problem, which if solved well, would definitely be useful to others too. I think the main reason YOU are stuck tackling this, is that there simply aren't all that many people who REALLY want or need your 'thousands of lightweight processes' use case. And of that set of people, you might be the only one who happens to be doing it with Tcl (and Naviserver), rather than one of the other dozens (or hundreds?) of plausible programming languages and toolkits. -- Andrew Piskorski <at...@pi...> http://www.piskorski.com/ |
From: Stephen D. <sd...@gm...> - 2008-05-11 13:42:43
|
On Sat, May 10, 2008 at 2:27 PM, Vasiljevic Zoran <zv...@ar...> wrote: > > On 09.05.2008, at 20:44, Vasiljevic Zoran wrote: > >> What MIGHT work is kind of this: create some numbers of >> fully loaded interps, each sitting in its own thread. >> A compute-farm, so to say. Then every other thread just >> creates a slave interp in one of those and runs all its >> scripts in his private slave in one of those parked threads >> in the compute-farm, using some kind of message passing. >> The slaves have all the commands aliased into the main >> one. Not sure what would happen with uplevels and upvars >> here (need to think) but this is roughly what I'm >> contemplating about now. > > Upvars/Uplevels will not work. No way. > >> So when a thread exits, its >> thin-slave is just deleted completely. And created it is >> also fast. Just alias all commands from the master. Not >> sure about the global variables... this is still open. > > No access to variables... > So: no generic solution as I was looking after. > Undocumented: generic/tclResolve.c: Tcl_AddInterpResolvers() You could probably even fake-up a solution using a single interp with your own name resolvers. Before you start executing the code for a single client, set a 'context' global which your resolver routines will use to keep state variables separate for each client. |
From: Vasiljevic Z. <zv...@ar...> - 2008-05-15 17:53:08
|
On 11.05.2008, at 15:42, Stephen Deasey wrote: > > Undocumented: > > generic/tclResolve.c: Tcl_AddInterpResolvers() > > > > You could probably even fake-up a solution using a single interp with > your own name resolvers. Before you start executing the code for a > single client, set a 'context' global which your resolver routines > will use to keep state variables separate for each client. Hmhmhm... I do not really follow.... I cannot do that with a single interp. As it is bound to a thread. So - single interp - single thread. How do I scale? I normally have, say, couple of hundred of connections to the server, all with a separate state. The simple and most straight forward is to keep that state (a connection socket to the client, client's private data) in a per-client sandbox. At the moment a Tcl interp and separate thread give me the needed "sandbox". Yet, currently that would blow the servers memory given my app metrics. To make the sandbox small, I just create an empty interp and route (message-passing) API calls to _something_ else. This keeps the sandbox reasonably small. I was hoping to find a generic solution to this, yet I do not know how :-( My only chance is to rewrite (or write new) app logic that encapsulates the required functionality in a high-level API and then route API calls to a battery of equally-created-threads, each fully loaded with the complete command set and state. The [ns_job] is quite a good example to what I need. But it is clumsy to use. Ideally, one would just call API calls directly in Tcl and that would automagically be ran in some distant/other interp. Well, that means, of course that API needs to be completely wrapped in the sense that I can only communicate scalar values with it (no refrerences, file handles, other handles etc pp) as the whole API state is uknown in the sandbox AND I have no per-interp affinity in my "computing-battery-of-threads" as this would limit my scalability. Now, I hope I managed to convey the picture. How do you see the above Tcl API could help me? What I understand is that this is ment to be helpful for extension writers to impmenent new language extensions (oo systems in particular) with custom var and command resolvers but all this is private to the calling thread. Or isn't it? Cheers Zoran |
From: Stephen D. <sd...@gm...> - 2008-05-23 20:27:59
|
On Thu, May 15, 2008 at 6:52 PM, Vasiljevic Zoran <zv...@ar...> wrote: > > On 11.05.2008, at 15:42, Stephen Deasey wrote: > >> >> Undocumented: >> >> generic/tclResolve.c: Tcl_AddInterpResolvers() >> >> >> >> You could probably even fake-up a solution using a single interp with >> your own name resolvers. Before you start executing the code for a >> single client, set a 'context' global which your resolver routines >> will use to keep state variables separate for each client. > > Hmhmhm... I do not really follow.... > > I cannot do that with a single interp. As it is bound to a thread. > So - single interp - single thread. How do I scale? You mentioned that you didn't want to rewrite a complicated state machine that uses a lot of uplevels, in an event style. I thought maybe you could keep the variables separate using these namespace lookup procs. Then you could use a single interp to manage multiple state machines, instead of using the stacks of 1000 threads. You could give each client an id on first connect and put them in buckets, with buckets >=1 and <= 1000. You need a pool of threads, one for each bucket. When a message arrives from a client, you sent it to the same thread/bucket each time. The interps of those threads are persistent. Within the bucket interps you use the namespace lookup trick to subdivide the variable space between the clients which are assigned to that interp. The interp runs a client message to completion, then picks up the next. Your concurrency level is however many buckets you decide to subdivide the 1000 connections into. |