Timer
thread on which to wait if a timeout value was specified; not sure if this is a dedicated thread or a multiplexed thread. If dedicated, doesn't that inflate the thread count horribly? I looked at Akka's source and it seems that futures are interrupted periodically in order to ask "Have I timed out yet?" ... keeps the thread count down, and probably costs less than a thread context switch.Future
combinators to compose actions."Future.select
, Future.join
Akka is missing select
and join
"
vars must be declared volatile in order for them to be published to other threads"
Finagle's Future.proxyTo seems very nice, not aware of a similar feature in the Akka Future API.
Finagle is missing Future.withFilter(); users won't miss it, however.
The default Akka Scheduler is based on the Netty implementation of
HashedWheelTimer.
>
> Finagle: use try/catch
> Akka: various error handling constructs, including recover and the seriously
> under-documented recoverWith (a code example would be very nice - hint,
> hint!)
Finagle uses the Try construct, Akka uses Either.
>
> Finagle: "You are discouraged from creating your own Promises. Instead,
> where possible, use Future combinators to compose actions."
> Akka: Use of Promises is encouraged and is very useful.
Yes, using Promises directly means you can use the Dataflow API, which
is very nice from a syntactical perspective.
>
> Finagle has Future combinators. Future.select, Future.join
> Akka is missing select and join
I don't know what select/join does, but akka has: fallbackTo and zip
>
> Finagle's Future.collectO seems similar to Akka's Future.sequence() and
> traverse()
>
> Finagle does not have Await.result() so many lines of code need to be
> written if a timeout handler is desired.
>
> Twitter's "Effective Scala" states "vars must be declared volatile in order
> for them to be published to other threads"
> No mention of volatile in the Akka docs.
We should probably add a section about Futures and the JMM in the Akka
docs, open a ticket. We already have Actors & JMM and STM & JMM
Seems like that cannot be the whole
> story. Too much has been left unsaid by the Akka docs and the Finagle docs.
Like what? We can't fix what you don't say.
>
> Finagle's FuturePool seems like an overly complex alternative to Akka's
> Future.blocking()
>
> Finagle's Future.proxyTo seems very nice, not aware of a similar feature in
> the Akka Future API.
Promise.completeWith
>
> Finagle is missing Future.withFilter(); users won't miss it, however.
>
> Finagle requires the user to set up a j.u.c. Executor, no nice configurable
> Akka factory.
You mean like ThreadPoolConfig?
Cheers,
√
>
> What have I missed or misquoted?
>
> Mike
>
> --
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/akka-user/-/3VrLg855SrAJ.
> To post to this group, send email to akka...@googlegroups.com.
> To unsubscribe from this group, send email to
> akka-user+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/akka-user?hl=en.
--
Viktor Klang
Akka Tech Lead
Typesafe - The software stack for applications that scale
Twitter: @viktorklang
Wdym?
Cheers,
V
>
>
> Mike
>
> --
> You received this message because you are subscribed to the Google Groups "Akka User List" group.
> To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/9RbDnkjvQiEJ.
Akka Futures will essentially become the Scala standard library
Futures with SIP-14
>
> I see now that Finagle uses the Future implementation from Twitter Utils, so
> Finagle is not required if you want futures but are not specifically
> interested in RPC. Not sure what other dependencies Twitter futures might
> require in order to be useful. Twitter's Scala School shows a Callback
> object but I don't see it in the code.
Twitter's Futures and Promises are from twitter-util, and are
standalone in that sense.
I'm hoping with SIP-14 that the Scala ecosystem will gravitate towards
using the standard library,
so we don't need 12372834627834 different Futures implementations.
>
> BTW, it looks like Twitter Futures does indeed require a thread for each
> future that wants a Timer. That is not a good use of resources. I am
> beginning to read about HashedWheelTimer now, looking at source, viewing
> presentation. I wonder if HashedWheelTimer would work with Twitter Futures.
I can only speak for Akka Futures & Promises.
Cheers,
√
>
>
> Mike
>
> --
> You received this message because you are subscribed to the Google Groups
> "Akka User List" group.
> To view this discussion on the web visit
> https://groups.google.com/d/msg/akka-user/-/GBdNYE0-6gcJ.
>
> To post to this group, send email to akka...@googlegroups.com.
> To unsubscribe from this group, send email to
> akka-user+...@googlegroups.com.
> For more options, visit this group at
> http://groups.google.com/group/akka-user?hl=en.
--
On Sun, Feb 12, 2012 at 5:11 PM, marius a. eriksen
<marius....@gmail.com> wrote:
> 2) Twitter futures don't prescribe any execution environment.
> That is: they are purely a coordination mechanism, and
> callbacks are run in whatever thread satisfies the promise, or
> in the same thread if the promise is already complete. This
> does mean that whenever you have blocking computation, you
> need to take care to execute these in your own threadpool --
> but again, we think of Futures as the coordination mechanism,
> and if there is blocking work, we represent the result of this
> as another future which can be combined in whatever ways are
> approriate.
>
Some background on the Akka 1.2 behavior here:
https://www.assembla.com/spaces/akka/tickets/1054-complete-futures-asynchronously-when-replying-through-a-channel
http://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/
I'm not familiar with the new Akka 2.0 Future.blocking stuff, I
haven't had a chance to look at it.
As you can probably tell from my blog post above, to me the important
thing is that it has to be defined and documented whether the
callbacks are run same-stack or different-stack. Either specification
can work well but leaving it undefined in my experience creates a
dangerous (= bug-prone, hard to use and test properly) API.
Havoc
Big disclaimer: I have not worked with Akka's futures. I only knowthem from their documentation and API docs as well as from SIP-14.Also: we've been working with Phillip, Heather, and co. to see if wecan consolidate these APIs somehow. As Viktor said, it'd be nice ifthere were just one API, and maybe even just one implementation.
> Both have onSuccess and onFailure; only Akka has onComplete.onComplete sounds like Twitter's "ensure"
> Finagle has a Timer thread on which to wait if a timeout value was> specified; not sure if this is a dedicated thread or a multiplexed> thread. If dedicated, doesn't that inflate the thread count horribly?> I looked at Akka's source and it seems that futures are interrupted> periodically in order to ask "Have I timed out yet?" ... keeps the> thread count down, and probably costs less than a thread context> switch.You pass in a timer to Future.within -- this is typically a sharedtimer. For example in Finagle we have only one timer that's sharedacross all timeouts. Like akka, we use Netty's HashedWheelTimer.
CALLBACK INVOCATION ORDERINGAs far as I can tell there is no way to provide callback orderingguarantees with this SIP. That makes it quite difficult to implement"try-finally" patterns. We do this quite often in our code:val resource = acquire()resource.operation() onSuccess { value =>resource.anotherOperation()} ensure {resource.release()}
CANCELLATION
FUTURE MERGING AND TAIL RECURSION
For example at one point the docs say "synchronously (blocking) or
asynchronously (non-blocking)" but I would distinguish the two.
Here are two possible definitions:
* asynchronous: runs without the current stack frame. Because it's
either on another thread's stack, or in this same thread but "later"
(after the current stack frame has been popped), or with the current
stack frame saved as a continuation and then resumed.
* nonblocking: does not tie up a thread while failing to use CPU. (on
the OS level, does not wait on a descriptor/handle/lock or equivalent;
does not suspend the thread waiting for the OS kernel to re-awaken it)
Another example of confusing this stuff, there was some recent
anti-node.js rant blog post going around that equated "spending time
using CPU" with "blocking" and that distinction in particular is
pretty important in my opinion. If you are blocking on IO/locks, then
tying up a thread is a massive waste of memory resources. If you are
spending time using CPU, then tying up a thread (ideally one thread
out of a pool matching number of CPU cores) is exactly what you want
to do; having an unbounded number of threads using CPU is bad. So the
analysis of node.js was muddled as a result of conflating these
distinct cases.
Anyhow, for explaining something like Future.blocking, I would think
the semantics in these kind of terms have to be made crystal clear; do
I use Future.blocking for long-running CPU-bound computation? For
blocking IO only? etc.
Havoc
Very interesting. I haven't yet dug very deep into Twitter's implementation, but it does look like both implementations have quite similar semantics. We must all be on the right track. I added a few comments below:On Sun, Feb 12, 2012 at 3:11 PM, marius a. eriksen <marius....@gmail.com> wrote:
Big disclaimer: I have not worked with Akka's futures. I only knowthem from their documentation and API docs as well as from SIP-14.Also: we've been working with Phillip, Heather, and co. to see if wecan consolidate these APIs somehow. As Viktor said, it'd be nice ifthere were just one API, and maybe even just one implementation.Any comments I add here are based on current Akka, I haven't been following too closely any changes proposed for the SIP.> Both have onSuccess and onFailure; only Akka has onComplete.onComplete sounds like Twitter's "ensure"I think it's identical to Twitter's 'respond', and in the scaladocs it sounds like it is the main building block of the other callback methods, just like onComplete is the base of all it's callback methods.
The main difference is that Akka requires the new Future to contain the result of the callback, where I think Twitter's just returns a new Future that points at the old value.(a side note: I might not be looking at Twitter's latest code... I can't seem to find Future.ensure?)
CANCELLATIONAkka does allow cancellation, but it is more basic then what Twitter has. In Akka the original Promise would just be completed with some cancellation exception, just like it handles timeouts. I need to dig deeper into this if I want to understand Twitter's implementation of this, as I think it is the one big different between Akka and Twitter.
FUTURE MERGING AND TAIL RECURSIONI don't think I can comment on any of this yet since I only had a quick look, and I can't decide yet if this is something that Akka's Future could benefit from or not. I think it may be due to Twitter's chaining of Futures so ensure ordering of callback's, where as Akka only ensures the order of callbacks by using methods like map/flatMap (a for-comprehension being a good example of how to ensure order).Also, it looks like Twitter's cancellation support also means that there are references kept for each Future created in the chain, where Akka has no need to hold onto any references... so it may have to do with this as well.Akka's Future currently only contains 2 variables: the executor (for any callbacks that need to run, can possibly be moved to the callback methods themselves as an implicit, but stored in the Future to keep the api simpler) and the current state (this variable could be a list of callbacks, or an Either[Throwable, T]), so there isn't a whole lot of state that could be shared between multiple Futures, the executor is already shared, and final result, if the same object, is already shared.But I could be completely off here. I'll need to look into it more, but my first instinct is that this is something Twitter's Future needs due to the way it implements callback ordering and/or cancellation.
I agree with your sentiments here. However, specifying callback semantics make it difficult to treat Futures as a pure coordination mechanism, since doing so would tie your implementation to an event loop, or an executor, or what have you. Therefore Twitter futures don't specify callback semantics, which in turn means that you should expect that your callback may be invoked directly, or it may be deferred. In practice, we use a combined approach: the first callback on a particular thread takes over the scheduler and further callbacks are deferred (unwound to the scheduler frame).
That alone still leaves a space leak, however.
--Thanks!Derek Williams
--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To post to this group, send email to akka...@googlegroups.com.
To unsubscribe from this group, send email to akka-user+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/akka-user?hl=en.
On Sun, Feb 12, 2012 at 11:54 PM, Marius Eriksen
<marius....@gmail.com> wrote:
> https://github.com/twitter/util/blob/master/util-core/src/main/scala/com/twitter/concurrent/IVar.scala#L83
That's pretty interesting. It isn't unlike having a trivial event loop
for each thread, I guess - though each "event" just triggers
immediately and isn't waiting for anything to happen.
I may not understand it, but I think if Schedule just had a way to
queue a callback, without running, then a program could create
always-defer semantics like this (adding hypothetical API):
val schedule = Schedule.get
schedule.queue(myActualCodeThatDoesStuff) // first part of current apply()
schedule.run() // run() part of current apply()
// thread exits or does something else
That's the usual API on event loops. It seems like the existing
schedule API more or less just automatically does the run() when you
enqueue the first task, so the first task is technically not deferred
(it runs with a "queueAndRun" - calling it apply() - on the stack):
schedule.queueAndRun(myActualCodeThatDoesStuff)
// thread exits or does something else
I'm wondering if this is an "always defers" API for practical
purposes, imagining:
def myActualCodeThatDoesStuff() {
takeSomeNonReentrantLock()
addSomeCallbackToSchedule(foo) // this will always defer
outside myActualCodeThatDoesStuff
dropLock()
// callback foo is going to run outside the lock
}
What I don't understand in Schedule is when run() would be invoked
recursively (via flush()?). I guess you could un-defer some callbacks
by recursing run()? And there you'd have to be aware of what the
callbacks were and be sure you dropped locks those callbacks might
need.
Anyway if I am roughly understanding Schedule it seems like you're
defining what's async and what isn't pretty carefully and there are
predictable semantics "every callback is deferred except the outermost
one, unless you flush() and then you better know what you're doing" ?
That's pretty deterministic from a programmer perspective.
In my blog post I was bringing up the old Akka version of the "!"
method which just didn't define at all the sync/async semantics;
assuming an interface with one method !, implementations of that
interface could either defer or not. As a practical matter, using an
interface like that, you often have to add an _extra_ manual defer
just to be sure it gets deferred. So that's the kind of ambiguous
interface that can be trouble.
> doing so would tie your implementation to an event loop, or an executor
it seems OK to me to have some pluggable "trait Deferer { def
defer(work: => Unit) }"
I mean, you can always implement it as "def defer(work: => Unit) {
work }" and force non-deferral
You could also implement it as "enqueue in the Schedule" as with the
code you linked above, perhaps?
Or it can be kicked to a thread pool...
The big difference between Schedule and deferring via executor seems
like it would be "same vs. different thread" which affects whether you
can block on the deferred thing...
Akka 2's "ExecutionContext" is this "trait Deferer" thing
> 2. locks in java/scala are by default reentrant (which of course can be
> the source of even subtler bugs!)
Where it came up for me in Akka is that actors are (as a core design
principle) not reentrant, of course.
As noted in my blog post it came up before Akka, when using
Hammersmith's netty connection and netty callbacks. Netty isn't
reentrant either presumably (I don't remember if the lock in question
was added by Hammersmith around the netty pipeline or was built-in to
netty).
In both of these cases, it was the "invoke application callback" that
needed to be deferred/async. The guideline could be reduced to: "don't
call out-of-your-own-module code with locks held." The ! method
processing messages synchronously was maybe an especially rocky case
of violating expectations, since that method is normally all about
being async.
> 3. not specifying callback semantics means the programmer cannot rely on
> them, maybe that makes them more aware
Tt isn't always clear what to do about it once you're aware - take the
case of Akka's pre-1.2 "!" method; you can fix the deadlock by
manually adding another layer of deferral, but then half the time you
have two layers of deferral. In this case as well, I doubt anyone
would be aware until they were bitten once. The "!" API is just flatly
more useful and less surprising if it has consistent semantics (= is
always async).
> I'm sure we have some bugs lingering, but it hasn't really come up.
My impression of that Schedule code is that you have pretty
well-specified behavior that almost always defers callbacks (unless
the callback is the outermost one, which is the least likely one to
hold locks or otherwise cause trouble)? I would not expect that to
cause a lot of bugs.
Code that bypassed the thread's Schedule and just ran a callback by
hand immediately, would be the more potentially troublesome case.
Sort of fun to think about Schedule as the world's tiniest event loop
implementation ;-)
Havoc
On Mon, Feb 13, 2012 at 7:02 AM, Derek Williams <de...@fyrie.net> wrote:On Sun, Feb 12, 2012 at 10:26 PM, Marius Eriksen <marius....@gmail.com> wrote:That alone still leaves a space leak, however.Ah, I think I get it now. Akka needs to hold a reference to each previous Future in order to have the final value returned. Definitely something to ponder.I don't see how one can cut corners here without reducing the power of the model.However, it could be rather easy to implement the Clojure equivalent of "transient" or the Scala "view" on Futures to coalesce such operations.
Please also note that this isn't a memory leak, since the memory will be reclaimed when the Future is not referenced anymore, and throughout the lifetime of Akka, I have had 0 issues reported regarding this.
There's this issue that while Actor makes threads go away and
developers don't have to think about them, Akka Future makes threads
come back and developers have to think about them again.
var state
def receive = {
...
something onComplete {
// code that runs in another thread
foo(state) // bad!
}
}
AFAIK current plans include methods like pipeTo and completeWith to
avoid writing callbacks by hand; and to make the compiler get upset if
you close actor state into the onComplete callback.
I guess there was an idea before, that onComplete's callback could run
serialized on the actor. The Schedule idea from IVar.scala is the same
thing applied to threads, using a thread local.
So you could imagine a DeferSerializedContext provided as an implicit
to onComplete and friends, perhaps. It would take a runnable and run
it later, but serialized same-actor or same-thread.
Outside of actors, futures could use a thread local or just a
manually-created context; inside, they use the actor. In both cases
all callbacks run deferred-but-serialized.
Outcome: using a Future by itself never exposes concurrency to the app
developer. Future doesn't dispatch anything to another thread or
actor, keeps it all in the same one.
Closing actor state into onComplete would be just fine, and often convenient.
When you need a new thread, you'd manually send to an executor, or
you'd create a new Actor instead of using threads.
Probably too much breakage for Akka but I still think it's an interesting angle.
Havoc
Hi,On Sun, Feb 12, 2012 at 11:54 PM, Marius Eriksen
<marius....@gmail.com> wrote:
> https://github.com/twitter/util/blob/master/util-core/src/main/scala/com/twitter/concurrent/IVar.scala#L83That's pretty interesting. It isn't unlike having a trivial event loop
for each thread, I guess - though each "event" just triggers
immediately and isn't waiting for anything to happen.I may not understand it, but I think if Schedule just had a way to
queue a callback, without running, then a program could create
always-defer semantics like this (adding hypothetical API):
val schedule = Schedule.get
schedule.queue(myActualCodeThatDoesStuff) // first part of current apply()
schedule.run() // run() part of current apply()
// thread exits or does something else
That's the usual API on event loops. It seems like the existing
schedule API more or less just automatically does the run() when you
enqueue the first task, so the first task is technically not deferred
(it runs with a "queueAndRun" - calling it apply() - on the stack):schedule.queueAndRun(myActualCodeThatDoesStuff)
// thread exits or does something elseI'm wondering if this is an "always defers" API for practical
purposes, imagining:def myActualCodeThatDoesStuff() {
takeSomeNonReentrantLock()
addSomeCallbackToSchedule(foo) // this will always defer
outside myActualCodeThatDoesStuff
dropLock()
// callback foo is going to run outside the lock
}What I don't understand in Schedule is when run() would be invoked
recursively (via flush()?). I guess you could un-defer some callbacks
by recursing run()? And there you'd have to be aware of what the
callbacks were and be sure you dropped locks those callbacks might
need.
Anyway if I am roughly understanding Schedule it seems like you're
defining what's async and what isn't pretty carefully and there are
predictable semantics "every callback is deferred except the outermost
one, unless you flush() and then you better know what you're doing" ?
That's pretty deterministic from a programmer perspective.
In my blog post I was bringing up the old Akka version of the "!"
method which just didn't define at all the sync/async semantics;
assuming an interface with one method !, implementations of that
interface could either defer or not. As a practical matter, using an
interface like that, you often have to add an _extra_ manual defer
just to be sure it gets deferred. So that's the kind of ambiguous
interface that can be trouble.> doing so would tie your implementation to an event loop, or an executor
it seems OK to me to have some pluggable "trait Deferer { def
defer(work: => Unit) }"I mean, you can always implement it as "def defer(work: => Unit) {
work }" and force non-deferralYou could also implement it as "enqueue in the Schedule" as with the
code you linked above, perhaps?Or it can be kicked to a thread pool...
The big difference between Schedule and deferring via executor seems
like it would be "same vs. different thread" which affects whether you
can block on the deferred thing...
Code that bypassed the thread's Schedule and just ran a callback by
hand immediately, would be the more potentially troublesome case.Sort of fun to think about Schedule as the world's tiniest event loop
implementation ;-)
Hi Jacobus,
Look up Scala Improvement Proposal 14, Akka 2.0 mimicks that API. Will be in Scala Std Lib in Future.
Cheers,
V
--
You received this message because you are subscribed to the Google Groups "Akka User List" group.
To view this discussion on the web visit https://groups.google.com/d/msg/akka-user/-/4wHnIr5CrCgJ.
I'm happy now :-)
Have a good one,
Jacobus
On Mon, Mar 12, 2012 at 11:14 AM, √iktor Ҡlang <viktor...@gmail.com> wrote:
> Scala Improvement Proposal 14