Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Revert ExecutionContext.global to not be a BatchingExecutor#9270

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
lrytz merged 1 commit intoscala:2.13.xfromdwijnand:revert-batching-global
Oct 23, 2020

Conversation

@dwijnand
Copy link
Member

@dwijnanddwijnand commentedOct 23, 2020
edited
Loading

NOTE This is a change in behaviour. If you make use ofscala.concurrent.ExecutionContext.global you may
want to adapt your code. Please note that Akka uses its own execution contexts (dispatchers) so is
unaffected.

In 2.13.0 we changed the behaviour ofExecutionContext.global so that it was more "opportunistic", by
attempting to batch nested task and execute them on the same thread as the enclosing task. Unfortunately this
relies heavily on the correct usage of theblocking { } wrapper on any long-running and/or blocking tasks;
code that didn't could end up executing serially instead of in parallel. As we believe that correct usage of
blocking isn't as well followed as hoped we decided torevertExecutionContext.global to its 2.12
behaviour and introduceExecutionContext.opportunistic for users that want to switch to it.

In order to maintain forwards and backwards binary compatibility of the scala standard library, the usage
instructions require some indirection. Library authors can use the opportunistic execution context for all
Scala 2.13.x versions like so:

implicitvalec: scala.concurrent.ExecutionContext=try {  scala.concurrent.ExecutionContext.getClass    .getDeclaredMethod("opportunistic")    .invoke(scala.concurrent.ExecutionContext)    .asInstanceOf[scala.concurrent.ExecutionContext]}catch {case_:NoSuchMethodException=>    scala.concurrent.ExecutionContext.global}

While application authors just need to gain access to theprivate[scala] field, which they can do by:

  1. Using a structural type (example below) which uses Java runtime reflection.
  2. Writing a Scalaobject in thescala package (example below).
  3. Writing a Java source file. This works becauseprivate[scala] is emitted aspublic in Java bytecode.

For example (option 1):

implicitvalec: scala.concurrent.ExecutionContext=  (scala.concurrent.ExecutionContext:    {defopportunistic: scala.concurrent.ExecutionContextExecutor}  ).opportunistic

Links:

Fixesscala/bug#12089

@scala-jenkinsscala-jenkins added this to the2.13.5 milestoneOct 23, 2020
@dwijnanddwijnand modified the milestones:2.13.5,2.13.4Oct 23, 2020
@lrytzlrytz merged commit79b4579 intoscala:2.13.xOct 23, 2020
@dwijnanddwijnand deleted the revert-batching-global branchOctober 23, 2020 12:05
@lrytz
Copy link
Member

Oh *?^!@#?#Q@ I didn't intend to merge this, I was on the wrong tab...

This needs a follow-up at least in documentation, to tell people about the batching alternative and how to get it

  • OnExecutionContext.global, maybe alsoExecutionContext.Implicits.global
  • Possibly in the@implicitNotFound onExecutionContext

Here is how users can create a batching EC instance in their codebase (code adapted from a draft by@viktorklang). Maybe this can be improved further, feedback welcome.2.13.x...lrytz:custom-batching-ec

We also plan to ship the batching EC in scala-library-next.

If preferred, we can revert this PR and re-submit it.

@viktorklang
Copy link
Contributor

@lrytz I have multiple issues with the proposal:

  1. Have "everyone" reimplement the 2.13 global behavior will reduce performance since batches won't be shared between different implementations
  2. Users who are depending on third-party library code which usesglobal have little chance of regaining lost performance since their dependency might have hard-coded the use of EC.global
  3. Implementing the 2.13 global behavior requires access to internal code, which will not be under binary compatibility guarantees (relying om implementation details)
  4. Users who lose performance due to the revert will likely only incidentally realize the cause
  5. Putting the 2.13 global behavior inscala-library-next has very limited discoverability and I'd wager that it will see little use (although I hope I am wrong)

@lrytz
Copy link
Member

Have "everyone" reimplement the 2.13 global behavior will reduce performance since batches won't be shared between different implementations

Users who are depending on third-party library code which usesglobal have little chance of regaining lost performance since their dependency might have hard-coded the use of EC.global

My assumption is that the actual EC used in an application is always imported (or defined) by the application's own source code - is that wrong? Are there libraries out there that use an EC internally without requiring it to be provided as parameter? To me this would seem to be a problematic design; any application that doesn't useglobal would run with multiple ECs.

Implementing the 2.13 global behavior requires access to internal code, which will not be under binary compatibility guarantees (relying om implementation details)

Yes, we're making theBatchingExecutor andPromise.Transformation classes accessible and we'll have to guarantee binary compatibility. The accessible members are

  • Promise.Transformation:public def benefitsFromBatching
  • BatchingExecutor:protected def submitForExecution,protected def reportFailure,protected final def submitAsyncBatched,protected final def submitSyncBatched

This looks reasonable to me, the risk of it causing problems in 2.13.x maintenance seems really low.

Users who lose performance due to the revert will likely only incidentally realize the cause

Putting the 2.13 global behavior inscala-library-next has very limited discoverability and I'd wager that it will see little use (although I hope I am wrong)

I agree this is a concern, but in my opinion the benefits of revertingglobal to its 2.12 behavior outweigh. Of course we will highlight the change in the announcements and release notes. We can work through documentation that we own to include references.

@dwijnanddwijnand added the release-notesworth highlighting in next release notes labelOct 26, 2020
@viktorklang
Copy link
Contributor

My assumption is that the actual EC used in an application is always imported (or defined) by the application's own source code - is that wrong? Are there libraries out there that use an EC internally without requiring it to be provided as parameter? To me this would seem to be a problematic design; any application that doesn't use global would run with multiple ECs.

What people are recommended to do, and what they actually do, was what ended us up in this situation in the first place :)

Yes, we're making the BatchingExecutor and Promise.Transformation classes accessible and we'll have to guarantee binary compatibility. The accessible members are

BatchingExecutor might not be an issue, but leaking internal Promise implementation details is a bit of a no-starter since it completely prevents the implementation to evolve. Also consider ScalaJS.

I agree this is a concern, but in my opinion the benefits of reverting global to its 2.12 behavior outweigh. Of course we will highlight the change in the announcements and release notes. We can work through documentation that we own to include references.

I hope you're right!

@lrytz
Copy link
Member

Two more things we can do:

  • Add the batching EC in aprivate[scala] field in 2.13.4
    • Application users (those not publishing a library) that have control over the Scala version at runtime could access that (there are ways to do so)
    • It could come in handy in the future, for example if there is more tooling in place so that a library could require a minimal Scala version
  • Mark the new public type aliases@deprecated with a clear message, and silence the depreaction in the code snippet for a user-defined batching EC with@nowarn

@viktorklang
Copy link
Contributor

@lrytz Adding theopportunistic EC (Batching on top ofglobal) as a private[scala] sounds good. A more ideal solution would be if one could have it be public, but with an @backwardsIncompatible annotation which would alert users that if they depend on it, it will not work with an older scala-lib (or even better, if an @since-annotation whose "minor" (epoch.major.minor) is not a "0" would automatically warn on compilation warning that using it means that the app is no longer backwards-compatible with an older scala-lib)

@lrytz
Copy link
Member

@backwardsIncompatible

This could be done with#8820

@dwijnanddwijnand mentioned this pull requestOct 28, 2020
72 tasks
@viktorklang
Copy link
Contributor

@dwijnand@lrytz Do you want me to open a PR with the private[scala]opportunistic EC so we can include it in 2.13.4?

@lrytz
Copy link
Member

That'd be welcome, thank you!

@viktorklang
Copy link
Contributor

hamzaremmal pushed a commit to hamzaremmal/scala3 that referenced this pull requestMay 2, 2025
Revert ExecutionContext.global to not be a BatchingExecutor
hamzaremmal pushed a commit to scala/scala3 that referenced this pull requestMay 7, 2025
Revert ExecutionContext.global to not be a BatchingExecutor
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

No reviews

Assignees

No one assigned

Labels

release-notesworth highlighting in next release notes

Projects

None yet

Milestone

2.13.4

Development

Successfully merging this pull request may close these issues.

Nested Future blocks do not run in parallel in Scala 2.13.x

4 participants

@dwijnand@lrytz@viktorklang@scala-jenkins

[8]ページ先頭

©2009-2025 Movatter.jp