Boost logo

Boost :

Subject: Re: [boost] Boost.Fiber review January 6-15
From: Oliver Kowalke (oliver.kowalke_at_[hidden])
Date: 2014-01-07 13:35:27


2014/1/7 Niall Douglas <s_sourceforge_at_[hidden]>

> Oh great! If you had a Design Rationale page which specifically says
> such a feature is out of scope for Boost.Fiber because it's a more
> complex additional layer which happens to be provided in another
> library X (preferably with link to it), then I would be very pleased.
>

I'll add an rational section to the documentation - the library is
pre-alpha (e.g.
I'm experimenting with some ideas - but if you are interested I can discuss
it
with you in a private email).

Well ... I agree that thread cancellation support is probably a step
> too far, but I think there is also a reasonable happy medium between
> C++11 and Boost.Thread.
>

I don't say that I'm against this - I've added fiber itnerruption (I would
follow the suggestion
from Herb Sutter that a thread/fiber should be cooperativ-cancelable ==
interruptable).
I try to keep the interface small as possible - of course we can discuss
which funtions
should the interface contain.

> Put it another way: what out of Boost.Thread's additions would look
> extremely likely to appear to C++17? The future::get_exception_ptr()
> is a very good example, it saves a lot of overhead when you're
> transferring exception state from one future to another.
>

This is one items which could be discussed. for instance I've concerns to
add future::get_exception_ptr() because I believe it is not really
required, it
is only for convenience. The exception thrown by the fiber-function
(function which
is executed by the fiber) is re-thrown by future<>::get().
If you don't want the exception re-thrown you could simply add a
try-catch-statement
at the top-most level in your fiber-function and assign the catched example
to an exception_ptr
passed to the fiber-function.

void my_fiber_fn( boost::exception_ptr & ep) {
  try {
     ...
   } catch ( my_exception const& ex) {
     ep = boost::current_exception();
   }
}

boost::exception_ptr ep;
boost::fibers::fiber( boost::bind( my_fiber_fn, boost::ref( ep) ) ).join();
if ( ep) {
   boost::rethrow_exception( ep);
}

I do think you need reference docs for the ASIO support classes.

I'll do it

> I don't understand what they do, and I think I ought to.
>

It is pretty simple - the fiber-scheduler contains a reference to asio's
io_service
and uses it a event-queue/event-dispatcher, e.g. it pushes fibers ready to
run
(e.g. fiber newly created, yielded fibers or signaled fibers suspended by a
wait-operation
on sync. primitives).

> Sure. But it's a "why should I use this library?" sort of thing? If I
> see real world benchmarks for a library, it tells me the author has
> probably done some performance tuning. That's a big tick for me in
> considering to use a library.
>

well I did not performance tuning - my main focus was to get the library
work correctly
(optimizations will we done later).

> It also suggests to me if refactoring my code is worth it. If
> Boost.Fiber provides only a 10x linear scaling improvement, that's
> very different from a log(N) scaling improvement. A graph making it
> very obvious what the win is on both CPU time and memory footprint
> makes decision making regarding Fiber support much easier.
>

I don't know the factor of fibers scaling - I would consider boost.fiber a
way
to simplify the code, e.g. it prevents scattering the code by callbacks
(for instance in the
context of boost.asio). my starting point was to solve problmes like the
C10K-problem
(Dan Kegel explains it in a more detail on its webpage - I'm referring to
it in boost.fiber's
documentation - http://olk.github.io/libs/fiber/doc/html/fiber/asio.html).

> Put it another way: if I am asking my management for time to
> prototype adopting Fibers in the company's core software, a scaling
> graph makes me getting that time a cinch. Without that graph, I have
> to either make my own graph in my spare time, or hope that management
> understands the difference between fibers and threads (unlikely).
>

well that are the problems we are all faced to :) I've not done
performance tests, sorry

> > Of course I could provide a benchmark for a simple task running a
> > certain amount of fibers - but what would be a good example for such a
> task?
>
> You don't need much: a throughput test of null operations (i.e. a
> pure test of context switching) for total threads 1...100,000 on some
> reasonably specified 64 bit CPU e.g. an Intel Core 2 Quad or better.
> I generally would display in CPU cycles to eliminate clock speed
> differences.
>

CPU cycles for context switching is provided for boost.context and
boost.coroutine - but
adapting the code for boost.fiber isn't an issue - I could addd it.

Extra bonus points for the same thing on some ARMv7 CPU.
>

counting CPU cycles isn't that easy for ARM (at least as I was looking at
it).

> Eh, well then I guess you need a link to the correct page in
> boost.context where it lists the architectures it works on. Certainly
> a big question for anyone considering Fiber is surely "will it work
> on my CPU"?
>

the docu of boost.context is mising this info - I'll add it (could you add
an bug-report for boost.context please).

> Sure, but I definitely won't be using Fibers that way. And I saw
> Antony had the same observation too. I think you need some more docs
> on this: just tell us what is possible, what works and how it works
> and we'll figure out the rest. I definitely need the ability to
> signal a fibre future belonging to thread A from some arbitrary
> thread B. I'll also need to boost::asio::io_service::post() to an
> ASIO io_service running fibers in thread A from some arbitrary thread
> B.
>

yes, as I explained it is supported.Maybe because I've writen the code
don't know why
the documentation is not enought for you.

what works is that you create fibers::packaged_task<> and execute it in a
fiber on thread A
and wait on fibers::future<> returned by packaged_task<>::get_future() in
thread B.

> The docs need to explicitly say so then, and indeed thread safety for
> *every* API in the library.
>

OK

> Complexity guarantees and exception safety statements for each API
> would also be nice. I know they're a real pain to do, but it hugely
> helps getting the library into a C++ standard later.
>

OK

> > between two threads (this code shows how work-stealing/work-sharing can
> be
> > implemented in a thread-pool).
>
> If you have a section in a design rationale page saying this, I would
> be happy.
>

OK

I think, as a minimum, all the examples need to appear verbatim in
> the docs
>

the complete code? I would prefer only code snippets - the complete code be
read in the
example directory. otherwise the documentation would be bloated (at least I
would skip pages of code).


Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk