Skip to content
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: Simplify flight recorder interactions #32499

Merged
merged 5 commits into from
Sep 9, 2024

Conversation

sebastian-alfers
Copy link
Contributor

chore: Simplify flight recorder interactions. Fixes #32309


  • Drop the actor extension approach.
  • Drop the akka.java-flight-recorder.enabled, to always recorder Flight Recorder interactions.
  • Drop the java version check.
  • Drop all NoOp fallbacks and let jvm'sx -XX:+UnlockCommercialFeatures -XX:+FlightRecorder handle any further usage.

"akka.actor.typed.internal.jfr.JFRActorFlightRecorder",
NoOpActorFlightRecorder)
}
lazy val recorder: ActorFlightRecorder = new JFRActorFlightRecorder()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can make the object the implementation instead of a separate singleton field, and then use that directly instead of a field in the classes that use it.

Copy link
Member

@johanandren johanandren left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

More fields to skip, I expect all to be internal so should be fine to mima filter them if MiMa is unhappy about dropping constructor parameters etc.

@@ -274,7 +274,7 @@ private class ConsumerControllerImpl[A] private (
import ProducerControllerImpl.Resend
import settings.flowControlWindow

private val flightRecorder = ActorFlightRecorder.recorder
private val flightRecorder = ActorFlightRecorder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And no need for this field or the parameter above, use the ActorFlightRecorder directly

@@ -448,7 +448,7 @@ private[akka] class Shard(

private val rememberEntities: Boolean = rememberEntitiesProvider.isDefined

private val flightRecorder = ShardingFlightRecorder.recorder
private val flightRecorder = ShardingFlightRecorder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use directly instead

@@ -284,7 +284,7 @@ private[remote] abstract class ArteryTransport(_system: ExtendedActorSystem, _pr

override val log: MarkerLoggingAdapter = Logging.withMarker(system, classOf[ArteryTransport])

val flightRecorder: RemotingFlightRecorder = RemotingFlightRecorder.recorder
private val flightRecorder = RemotingFlightRecorder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

drop field, and also the debug log statement below, it's there to know which recorder was used but now there is only one

@@ -150,7 +150,7 @@ private[remote] class Association(
require(remoteAddress.port.nonEmpty)

private val log = Logging.withMarker(transport.system, classOf[Association])
private def flightRecorder = transport.flightRecorder
private def flightRecorder = RemotingFlightRecorder
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

use directly

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove this def altogether?

@johanandren
Copy link
Member

Dang it, meant to comment, not to approve

# Some modules (remoting only right now) can emit custom events to the Java Flight Recorder if running
# on JDK 11 or later. If you for some reason do not want that, it can be disabled and switched to no-ops
# with this toggle.
java-flight-recorder {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should probably be mentioned in the release-notes MD?

Copy link
Member

@johanandren johanandren Sep 3, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, not a big problem but we should still mention

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, going to rebase on top of the merged #32497.

@@ -0,0 +1,8 @@
# #32499 chore: Simplify flight recorder interactions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The file name should be the latest release. Did this solve anything? Is it needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I changed the name 👍

Did this solve anything? Is it needed?

When I remove the content of the file, I get this error:

sbt:akka-actor> mimaReportBinaryIssues
[error] akka-actor: Failed binary compatibility check against com.typesafe.akka:akka-actor_2.13:2.6.7! Found 2 potential problems (filtered 112)
[error]  * class akka.util.FlightRecorderLoader does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("akka.util.FlightRecorderLoader")
[error]  * object akka.util.FlightRecorderLoader does not have a correspondent in current version
[error]    filter with: ProblemFilters.exclude[MissingClassProblem]("akka.util.FlightRecorderLoader$")
[error] stack trace is suppressed; run last mimaReportBinaryIssues for the full output
[error] (mimaReportBinaryIssues) Failed binary compatibility check against com.typesafe.akka:akka-actor_2.13:2.6.7! Found 2 potential problems (filtered 112)
[error] Total time: 0 s, completed Sep 4, 2024, 9:44:43 AM
sbt:akka-actor>

@@ -0,0 +1,3 @@
# #32499 chore: Simplify flight recorder interactions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

new TcpOutboundConnected(remoteAddress, streamName).commit()

def tcpOutboundSent(size: Int): Unit =
new TcpOutboundSent(size).commit()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we have to verify that it works as we expect? That this isn't adding any overhead when JFR isn't used? We had a description somewhere of how the jvm would omit this execution, but can't find it. I assume there wouldn't even be allocations of the events that could increase pressure on GC?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I have the same recollection. It should be escape analysed to zero allocation when enabled, but then also completely eliminated when JFR is disabled. I also don't have any reference though, so we should double check by running a benchmark with JFR disabled and look compare allocations (can't use JFR obviously :D)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe jmh with -prof gc would be sufficient

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, my thinking, before and after this change to compare allocation rate, maybe the CodecBenchmark I think that involves some of the remoting stream stages?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll do some verification bench runs today

@@ -0,0 +1,8 @@
# #32499 chore: Simplify flight recorder interactions
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2.9.5, not 2.9.5.0

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤦

@johanandren
Copy link
Member

Bench results looks good, I think the differences between main and this branch in my results is small enough to be just noise, and the normalised allocation rate looks the same (I expect it should be allocating noticeably more per op if our assumptions were true)

Raw output from runs and details:
jfr-object-bench-results.txt

@patriknw
Copy link
Member

patriknw commented Sep 4, 2024

Is the CodecBenchmark using RemotingFlightRecorder? I don't see that Encoder or Decoder stages are using it.

@johanandren
Copy link
Member

johanandren commented Sep 6, 2024

The InboundCompressionsImpl used by the decoder does, but now that I look closer it does not do a lot of JFR event emit (only on advertisement). I'll do my homework and run a better bench somehow.

@johanandren
Copy link
Member

New bench run, you can see bench details here https://github.com/akka/akka/compare/wip-jfr-simplify-bench?expand=1#diff-5716ff6ab54d9a1887ab449af41b3f2b185e83cb6a22bc8d5c3580b4cdf4bb00R1 , it basically compares alloc rate for incrementing a counter to 10 with counting to 10 calling RemotingFlightRecorder for every increment.

Result seems to confirm that those calls are thrown out by JIT:

[info] JfrOverheadBenchmark.withJfr                        thrpt    2  25358066,747          ops/ms
[info] JfrOverheadBenchmark.withJfr:gc.alloc.rate          thrpt    2         0,001          MB/sec
[info] JfrOverheadBenchmark.withJfr:gc.alloc.rate.norm     thrpt    2        ≈ 10⁻⁸            B/op
[info] JfrOverheadBenchmark.withJfr:gc.count               thrpt    2           ≈ 0          counts
[info] JfrOverheadBenchmark.withoutJfr                     thrpt    2  25071049,832          ops/ms
[info] JfrOverheadBenchmark.withoutJfr:gc.alloc.rate       thrpt    2         0,001          MB/sec
[info] JfrOverheadBenchmark.withoutJfr:gc.alloc.rate.norm  thrpt    2        ≈ 10⁻⁸            B/op
[info] JfrOverheadBenchmark.withoutJfr:gc.count            thrpt    2           ≈ 0          counts

@patriknw
Copy link
Member

patriknw commented Sep 9, 2024

thanks for the new bench

Copy link
Member

@patriknw patriknw left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sebastian-alfers sebastian-alfers merged commit b6501eb into akka:main Sep 9, 2024
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Simplify flight recorder interactions
3 participants