[context/coroutine] split into two libs in trunk?!

Hi, unfortunetly Giovanni decided to discontinue its boost.coroutine library and I was ask be several members of the boost community to provide a coroutine implementation using boost.context. I've refactored class context from lib boost.context so that I can provide coroutine<> and generator<> (following Giovannis interface proposal) based on context now. I'd like to split it into two libraries: - boost.context provides only context jumping facility (a.g. struct fcontext_t, start_fcontext()/jump_fcontext()/make_fcontext() and stack helper) - boost.coroutine contains coroutine<> and generator<> Might this be appropriate? regards, Oliver -- NEU: FreePhone 3-fach-Flat mit kostenlosem Smartphone! Jetzt informieren: http://mobile.1und1.de/?ac=OM.PW.PW003K20328T7073a

On Wed, Apr 11, 2012 at 10:41 PM, Oliver Kowalke <oliver.kowalke@gmx.de>wrote:
Hi,
unfortunetly Giovanni decided to discontinue its boost.coroutine library and I was ask be several members of the boost community to provide a coroutine implementation using boost.context. I've refactored class context from lib boost.context so that I can provide coroutine<> and generator<> (following Giovannis interface proposal) based on context now. I'd like to split it into two libraries:
- boost.context provides only context jumping facility (a.g. struct fcontext_t, start_fcontext()/jump_fcontext()/make_fcontext() and stack helper)
- boost.coroutine contains coroutine<> and generator<>
Might this be appropriate?
My preference at this phase in the moon (i.e., just thinking aloud at the moment) might be to have everything context-related be under a single heading, rather than be fragmented, just to express their close relationships. It might be easier then for someone who first looks at context to immediately realize that what they really want is one of the higher-level constructs. I might be worried about a non-existent problem, though! Suggestions for such a single heading, if we go that route: Fiber? Cooperative? My 2c, - Jeff

My preference at this phase in the moon (i.e., just thinking aloud at the moment) might be to have everything context-related be under a single heading, rather than be fragmented, just to express their close relationships. It might be easier then for someone who first looks at context to immediately realize that what they really want is one of the higher-level constructs. I might be worried about a non-existent problem, though!
Suggestions for such a single heading, if we go that route: Fiber? Cooperative?
not fiber! the reason I'm asking is that beside of boost.context (which should work as the basis for libs dealing with cooperative tasking) I've now a coroutine library (as requested by some memebers) and I've also the boost.stratified library almost ready (see stratified JS - cooperative too). I don't think it is a good idea to put all those stuff into one lib. regards, Oliver -- Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

On Wed, Apr 11, 2012 at 11:54 PM, Oliver Kowalke <oliver.kowalke@gmx.de>wrote:
My preference at this phase in the moon (i.e., just thinking aloud at the moment) might be to have everything context-related be under a single heading, rather than be fragmented, just to express their close relationships. It might be easier then for someone who first looks at context to immediately realize that what they really want is one of the higher-level constructs. I might be worried about a non-existent problem, though!
Suggestions for such a single heading, if we go that route: Fiber? Cooperative?
not fiber!
I take this to mean you don't like the name "fiber".
the reason I'm asking is that beside of boost.context (which should work as the basis for libs dealing with cooperative tasking) I've now a coroutine library (as requested by some memebers) and I've also the boost.stratified library almost ready (see stratified JS - cooperative too).
What do you mean by "see stratified JS - cooperative too"?
I don't think it is a good idea to put all those stuff into one lib.
I sympathize. I'm just looking to prevent over-fragmentation...Boost already has a lot of libraries, I mean, I'd imagine the number is large enough to be quite unwieldy to those new to Boost :/ And, to reiterate, I don't think it's totally crazy to put all the cooperative stuff under one heading. But maybe I'm just playing devil's advocate. Others should chime in. - Jeff

not fiber!
I take this to mean you don't like the name "fiber".
yes - because fiber is only one possible abstraction of cooperative multitasking.
What do you mean by "see stratified JS - cooperative too"?
stratified JavaScript is a framework which transforms async. operations using cooperative multitasking http://onilabs.com/presentations/OSCON2010/async.html boost.stratified should provide a similiar facility for C++ regards, Oliver -- NEU: FreePhone 3-fach-Flat mit kostenlosem Smartphone! Jetzt informieren: http://mobile.1und1.de/?ac=OM.PW.PW003K20328T7073a

On Fri, Apr 13, 2012 at 5:28 AM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
On 12/04/12 08:37, Jeffrey Lee Hellrung, Jr. wrote:
Suggestions for such a single heading, if we go that route: Fiber?
Cooperative?
Boost.Context can be used to implement preemptive (i.e. not cooperative) multithreading.
Is that feasible in practice? (Serious question; I'm not sure.) - Jeff

On 13/04/12 17:53, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, Apr 13, 2012 at 5:28 AM, Mathias Gaunard< mathias.gaunard@ens-lyon.org> wrote:
On 12/04/12 08:37, Jeffrey Lee Hellrung, Jr. wrote:
Suggestions for such a single heading, if we go that route: Fiber?
Cooperative?
Boost.Context can be used to implement preemptive (i.e. not cooperative) multithreading.
Is that feasible in practice? (Serious question; I'm not sure.)
A lot of libraries implement user-level threading. Fast context switching is the most sensitive component. AFAIK the HPX library, done by several people associated to Boost, uses code derived from the old Boost.Coroutine for context switching. Bryce Lelbach told me they didn't move to Boost.Context because it was slow and had significant scalability problems. I had asked him to give his experience during the Boost.Context review, but it seems he never did.

Am 13.04.2012 18:05, schrieb Mathias Gaunard:
AFAIK the HPX library, done by several people associated to Boost, uses code derived from the old Boost.Coroutine for context switching. Boost.Coroutine from Giovanni uses ucontext_t on UNIX.
Bryce Lelbach told me they didn't move to Boost.Context because it was slow and had significant scalability problems.
He never told that to me and I'm pretty sure that boost.context is much faster than boost.coroutine (from Giovanni) because the last one uses ucontext facility which does system calls in its jump functions - boost.context, e.g. fcontext_t and its related functions does not (implemented in assembler)! You can also take a look at the documentation, section performance - it shows that fcontext outperforms ucontext by factor 10. Oliver

On 13/04/12 18:28, Oliver Kowalke wrote:
Am 13.04.2012 18:05, schrieb Mathias Gaunard:
AFAIK the HPX library, done by several people associated to Boost, uses code derived from the old Boost.Coroutine for context switching. Boost.Coroutine from Giovanni uses ucontext_t on UNIX.
This is incorrect. ucontext is just one of the provided implementations. There is also custom assembly for x86. <https://svn.boost.org/svn/boost/sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/>

Am 13.04.2012 19:21, schrieb Mathias Gaunard:
On 13/04/12 18:28, Oliver Kowalke wrote:
Am 13.04.2012 18:05, schrieb Mathias Gaunard:
AFAIK the HPX library, done by several people associated to Boost, uses code derived from the old Boost.Coroutine for context switching. Boost.Coroutine from Giovanni uses ucontext_t on UNIX.
This is incorrect. ucontext is just one of the provided implementations. There is also custom assembly for x86.
<https://svn.boost.org/svn/boost/sandbox/SOC/2006/coroutine/trunk/libs/coroutine/src/>
what about the other architectures? and has to save/restore the registers as the call conventions require (and fcontext does). Why should it then be faster? At a brief look it does not preserve the SSE2 control and status word as well as it does not preserve x87 control word. If you do not take care about the calling convention and ignore to preserve some relevant data of course you can be faster (but it is incorrect code and might fail).

On Fri, Apr 13, 2012 at 7:39 PM, Oliver Kowalke <oliver.kowalke@gmx.de> wrote:
Am 13.04.2012 19:21, schrieb Mathias Gaunard:
This is incorrect. ucontext is just one of the provided implementations. There is also custom assembly for x86.
what about the other architectures? and has to save/restore the registers as the call conventions require (and fcontext does). Why should it then be faster? At a brief look it does not preserve the SSE2 control and status word as well as it does not preserve x87 control word. If you do not take care about the calling convention and ignore to preserve some relevant data of course you can be faster (but it is incorrect code and might fail).
Not saving the SSE and x87 control word was a conscious decision on my part. The control words are unlike other callee/caller saved registers as they define a process mode and are explicitly under the control of the user. In my tests the instructions used to load/save these states had a considerable cost on my old netburst CPU. The compiler may temporarily change the control state (for example in legacy x87 mode to implement some non-standard rounding), but it has to reset them to the original value before calling any externally defined function (like the ASM context switching functions) as these will expect the control words to be in the default state (whatever this is). The only time called functions will see the control words in a non default state is if the user explicitly changed the state, for example via a C99 compiler pragma or builtin function. The boost.coroutine documentation did explicitly warn about risky changes to proces state across coroutine calls, including the signal mask (which boost.context also does not preserve), locks, TLS and of course the FPU state. So, yes, the user might see failures, but never because of hidden optimizations done by the compiler, but because he explicitly forgot to restore the sahred state (any state) to a sane default before switching out of the coroutine. Having said that, I doubt that on a modern CPU this extra state save/change would hardly cost more than an extra 50% on a context call (which in the grand order of things isn't really that much). Any claimed scalability differences between boost.context and the my old library must come from somewhere else and not from the low lever context switching routines. The only thing that comes to my mind is that boost.coroutine did save all registers on the stack (which is very likely to be cache hot) instead of a separate structure as for boost.context (which, IIRC, was heap allocated in the higher lever wrapper). FWIW, while it is hard to compare my results on an old 32 bit machine with yours on an undoubtely newer CPU and OS, I distinctly remember from my tests that a coroutine-to-coroutine switch (using the high level API) was about an 100 time faster using the custom backend than using ucontext (mainly because of the high cost of the function call). HTH, -- gpd

Am 14.04.2012 00:37, schrieb Giovanni Piero Deretta:
Not saving the SSE and x87 control word was a conscious decision on my part. The control words are unlike other callee/caller saved registers as they define a process mode and are explicitly under the control of the user. In my tests the instructions used to load/save these states had a considerable cost on my old netburst CPU.
The compiler may temporarily change the control state (for example in legacy x87 mode to implement some non-standard rounding), but it has to reset them to the original value before calling any externally defined function (like the ASM context switching functions) as these will expect the control words to be in the default state (whatever this is).
The only time called functions will see the control words in a non default state is if the user explicitly changed the state, for example via a C99 compiler pragma or builtin function. The boost.coroutine documentation did explicitly warn about risky changes to proces state across coroutine calls, including the signal mask (which boost.context also does not preserve), locks, TLS and of course the FPU state. but what about code you don't have under your control (legacy libs etc.)? Having said that, I doubt that on a modern CPU this extra state save/change would hardly cost more than an extra 50% on a context call (which in the grand order of things isn't really that much). Any claimed scalability differences between boost.context and the my old library must come from somewhere else and not from the low lever context switching routines. The only thing that comes to my mind is that boost.coroutine did save all registers on the stack (which is very likely to be cache hot) instead of a separate structure as for boost.context (which, IIRC, was heap allocated in the higher lever wrapper). I you refer to my performance tests - I never compared boost.context with boost.coroutine - I've measured the cycle-costs of fcontext and ucontext.
FWIW, while it is hard to compare my results on an old 32 bit machine with yours on an undoubtely newer CPU and OS, I distinctly remember from my tests that a coroutine-to-coroutine switch (using the high level API) was about an 100 time faster using the custom backend than using ucontext (mainly because of the high cost of the function call).
HTH, that was the same what I figured out (see above fcontext vs. ucontext and performance test app in boost.context). I assumed that your lib used ucontext as back-end and therefore I've had concerns about that it would be much faster than boost.context (as told in another post).
btw, file swapcontext64.cpp (from your lib) might contain a bug https://svn.boost.org/svn/boost/sandbox/SOC/2006/coroutine/trunk/libs/corout... it preserves the registers rbx, rbp, rax , rdx. I think it should be rbx, rbp, r12-r15 (+SSE2 and x87) as described in' SysV ABI AMD64 Architecture Processor Supplement - Draft Version 0.99.4'.

Am 14.04.2012 00:37, schrieb Giovanni Piero Deretta:
Having said that, I doubt that on a modern CPU this extra state save/change would hardly cost more than an extra 50% on a context call (which in the grand order of things isn't really that much). Any claimed scalability differences between boost.context and the my old library must come from somewhere else and not from the low lever context switching routines.
boost.context uses a lot of BOOST_ASSERT-statements for testing pre- and postconditions taking care about the internal state of the context. of course without defining BOOST_DISABLE_ASSERTS you measure the extra cycles of the pre-and postconditions tests too.

On Fri, Apr 13, 2012 at 9:05 AM, Mathias Gaunard < mathias.gaunard@ens-lyon.org> wrote:
On 13/04/12 17:53, Jeffrey Lee Hellrung, Jr. wrote:
On Fri, Apr 13, 2012 at 5:28 AM, Mathias Gaunard< mathias.gaunard@ens-lyon.org> wrote:
On 12/04/12 08:37, Jeffrey Lee Hellrung, Jr. wrote:
Suggestions for such a single heading, if we go that route: Fiber?
Cooperative?
Boost.Context can be used to implement preemptive (i.e. not cooperative) multithreading.
Is that feasible in practice? (Serious question; I'm not sure.)
A lot of libraries implement user-level threading. Fast context switching is the most sensitive component.
AFAIK the HPX library, done by several people associated to Boost, uses code derived from the old Boost.Coroutine for context switching.
Bryce Lelbach told me they didn't move to Boost.Context because it was slow and had significant scalability problems. I had asked him to give his experience during the Boost.Context review, but it seems he never did.
Perhaps, then, it would be more appropriate for there to be a Boost.Context library and separate Boost.Cooperative library, the latter of which would include Coroutine, Generator, Stratified, etc....? Or is there another umbrella term appropriate for all of these components? E.g., Multitask, or something? - Jeff

Am 13.04.2012 18:05, schrieb Mathias Gaunard:
Bryce Lelbach told me they didn't move to Boost.Context because it was slow and had significant scalability problems. I had asked him to give his experience during the Boost.Context review, but it seems he never did.
I did a performance test (included in my lib -> directory performance) which measures the costs of a context jump. the result of Giovannis Boost.Context and my implementation (whic hyou told is slow and significant scalability problems): CPU cycles per jump with enabled BOOST_ASSERT (1000 iterations, average of 10 executions): - Giovannis implementation : 561 cycles - my implementation: 371 cycles CPU cycles per jump with disabled BOOST_ASSERT (1000 iterations, average of 10 executions): - Giovannis implementation : 556 cycles - my implementation: 337 cycles

Oliver Kowalke wrote
Hi,
unfortunetly Giovanni decided to discontinue its boost.coroutine library and I was ask be several members of the boost community to provide a coroutine implementation using boost.context. I've refactored class context from lib boost.context so that I can provide coroutine<> and generator<> (following Giovannis interface proposal) based on context now.
Hi Oliver, What kind of changes have been needed to make it possible to implement coroutine and generator?
I'd like to split it into two libraries:
- boost.context provides only context jumping facility (a.g. struct fcontext_t, start_fcontext()/jump_fcontext()/make_fcontext() and stack helper)
- boost.coroutine contains coroutine<> and generator<>
Might this be appropriate?
I see 3 valid alternatives here: * You provide it as sub-library coroutine of context. * You request for review a separated coroutine proposal. * You rename your context library as cooperative/context and add the cooperative/coroutine, cooperative/fiber, ..... This will need at least a mini-mini review to change the goal, the name and the directory of the library. This alternative would not prevent to request less formal review or formal ones if you find it useful. I would prefer a change the top level namespace to cooperative in this case. The alternatives are in the reverse order of my preference. I agree with Jeffrey that we need less top level libraries, and have sub-libraries. For example Boost.Thread contains the review accepted Boost.Futures. Is this clearer for the users? I would like to have e.g. under the umbrella of Boost.Utility 'everything' that 'every' programmer needs. I don't know yet if Boost.Chrono will include or not a Stopwatch or a Date (not a DateTime) sub-library but I think at least an informal review would be needed to ensure the Boost quality. This will give the opportunity to the Boost community to signal if a formal review will be more convenient. Best, Vicente -- View this message in context: http://boost.2283326.n4.nabble.com/context-coroutine-split-into-two-libs-in-... Sent from the Boost - Dev mailing list archive at Nabble.com.

What kind of changes have been needed to make it possible to implement coroutine and generator?
the context class, which holds a pointer do context_base class, is now transformed to a template (e.g. Signature as template arg) but still holds a pointer to context_base class which did not change. I'm using the 'curiously recurring template pattern' for the interface generation.
I see 3 valid alternatives here: * You provide it as sub-library coroutine of context. * You request for review a separated coroutine proposal. * You rename your context library as cooperative/context and add the cooperative/coroutine, cooperative/fiber, ..... This will need at least a mini-mini review to change the goal, the name and the directory of the library. This alternative would not prevent to request less formal review or formal ones if you find it useful. I would prefer a change the top level namespace to cooperative in this case.
OK - I would rename boost.context to cooperative/context. How should this mini-mini review take place? Do I've to ask on the mailing list or would be the conclusions of this thread enought? regards, Oliver -- Empfehlen Sie GMX DSL Ihren Freunden und Bekannten und wir belohnen Sie mit bis zu 50,- Euro! https://freundschaftswerbung.gmx.de

Le 12/04/12 11:24, Oliver Kowalke a écrit :
What kind of changes have been needed to make it possible to implement coroutine and generator? the context class, which holds a pointer do context_base class, is now transformed to a template (e.g. Signature as template arg) but still holds a pointer to context_base class which did not change. I'm using the 'curiously recurring template pattern' for the interface generation.
I see 3 valid alternatives here: * You provide it as sub-library coroutine of context. * You request for review a separated coroutine proposal. * You rename your context library as cooperative/context and add the cooperative/coroutine, cooperative/fiber, ..... This will need at least a mini-mini review to change the goal, the name and the directory of the library. This alternative would not prevent to request less formal review or formal ones if you find it useful. I would prefer a change the top level namespace to cooperative in this case. OK - I would rename boost.context to cooperative/context. How should this mini-mini review take place? Do I've to ask on the mailing list or would be the conclusions of this thread enought?
I gues that you will need to request it formally to the review wizards, but wait a little bit to see what others think. Vicente

On Thu, Apr 12, 2012 at 2:24 AM, Oliver Kowalke <oliver.kowalke@gmx.de>wrote:
What kind of changes have been needed to make it possible to implement coroutine and generator?
the context class, which holds a pointer do context_base class, is now transformed to a template (e.g. Signature as template arg) but still holds a pointer to context_base class which did not change. I'm using the 'curiously recurring template pattern' for the interface generation.
I see 3 valid alternatives here: * You provide it as sub-library coroutine of context. * You request for review a separated coroutine proposal. * You rename your context library as cooperative/context and add the cooperative/coroutine, cooperative/fiber, ..... This will need at least a mini-mini review to change the goal, the name and the directory of the library. This alternative would not prevent to request less formal review or formal ones if you find it useful. I would prefer a change the top level namespace to cooperative in this case.
OK - I would rename boost.context to cooperative/context. How should this mini-mini review take place? Do I've to ask on the mailing list or would be the conclusions of this thread enought?
I think if everyone is aware of the reorganization and no one objects, a (mini-)* review maybe wouldn't be necessary? Maybe send personal emails to those involved in the Context review to ensure they're aware of any proposed changes? - Jeff
participants (6)
-
Giovanni Piero Deretta
-
Jeffrey Lee Hellrung, Jr.
-
Mathias Gaunard
-
Oliver Kowalke
-
Vicente Botet
-
Vicente J. Botet Escriba