-
Notifications
You must be signed in to change notification settings - Fork 154
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
chore: Add FutureOps which with an await style. #1666
base: main
Are you sure you want to change the base?
Conversation
ef0b126
to
ba09de8
Compare
This code is internal. Does it matter if it is fluent? |
So does performance, I think which will avoid the waiting if the future is already done. I was want to make this public, but it seems safer for me to taste it first. |
If there is a perf issue in Await.result, I would prefer it was fixed in Scala runtime. The Scala 2 impl seems to try to optimise for the completed case.
|
The code seems need more adjustment, as we don't need to test if it's a future anymore |
??? Why its closed? |
*/ | ||
def await(atMost: Duration = Duration.Inf): T = future.value match { | ||
case Some(value) => value.get | ||
case None => blocking(future.result(atMost)(null)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
avoid the double checking now
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
final def resultOption[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable match {
case CompletedFuture(v) => v.get
case _ => blocking(awaitable.result(atMost)(AwaitPermission))
}
private final object CompletedFuture {
def unapply[T](f: Future[T]): Option[Try[T]] = f.value
}
@pjfanning I have attached the result |
I would still like this discussed with the Scala team to understand if the Await.result can be improved. Everyone benefits if you have discovered a perf issue there and that it then gets fixed. |
@pjfanning scala/scala#10972 , submitted to scala |
Awesome that you have proposed this improvement upstream, thanks! I see two motivations for this change: the performance improvement, and the fact that the code 'looks nicer'. I agree that if this performance improvement could make it upstream that would be much better. For the idea that this change makes the code looks nicer, I'm not sure I agree: it replaces well-known Scala idiom with a custom helper. While the custom helper is perhaps nicer, it's also 'one more thing to learn'. Also, because asynchronicity is at the heart of Pekko, we should use |
extension [T](src: Source[scala.util.Try[T]])
/** Waits for an item to arrive from the source, then automatically unwraps it. Suspends until an item returns.
* @see
* [[Source!.awaitResult awaitResult]] for non-unwrapping await.
*/
inline def await(using Async) = src.awaitResult.get and then with usage: test("Constant returns") {
Async.blocking:
for (i <- -5 to 5)
val f1 = Future { i }
val f2 = Future.now(Success(i))
assertEquals(f1.await, i)
assertEquals(f1.await, f2.await)
}
def unwrap: Try[T] in Future.scala, and then @throws(classOf[TimeoutException])
@throws(classOf[InterruptedException])
final def result[T](awaitable: Awaitable[T], atMost: Duration): T = awaitable match {
case f: Future[T] @unchecked =>
val r = f.unwrap
if (r ne null) r.get
else blocking(awaitable.result(atMost)(AwaitPermission))
case _ => blocking(awaitable.result(atMost)(AwaitPermission))
} But the result doesn't have much difference in gc pressure. |
One advantage of having this inside is it works on all scala versions. |
@He-Pin could you add the CompleteFutureBenchmark to this PR? I think we have some benchmarks in this repo where this could be added. |
// jmh:run -i 11 -wi 11 -f1 -t1 org.apache.pekko.util.FutureOpsBenchmark | ||
// [info] Benchmark Mode Cnt Score Error Units | ||
// [info] FutureOpsBenchmark.awaitWithAwaitable thrpt 11 706198.499 ± 8185.983 ops/ms | ||
// [info] FutureOpsBenchmark.awaitWithFutureOps thrpt 11 766901.781 ± 9741.792 ops/ms |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@pjfanning Attached.
I would like us to take a little bit of time over this just to see what the Scala team and other users have to say. |
@pjfanning I think that will not make much difference, the old implementation will always do the |
And I think there is a limitation of the current Scala implementation, were we can't save the https://contributors.scala-lang.org/t/inline-convertion-in-pattern-matchings-if-guard/6962/12 |
Motivation:
I found the
Await.result
is everywhere.Modification:
Add an
await
operator to the future.Result:
Fluent code.
I did some changes in the scala/scala