Skip to content

Conversation

@zhengyu123
Copy link
Contributor

What does this PR do?:

Motivation:

Additional Notes:

How to test the change?:

For Datadog employees:

  • If this PR touches code that signs or publishes builds or packages, or handles
    credentials of any kind, I've requested a review from @DataDog/security-design-and-guidance.
  • This PR doesn't touch any of that.
  • JIRA: [JIRA-XXXX]

Unsure? Have a question? Request a review!

@zhengyu123 zhengyu123 requested review from ivoanjo, jbachorik and r1viollet and removed request for ivoanjo October 24, 2025 21:39
@zhengyu123 zhengyu123 marked this pull request as ready for review October 24, 2025 21:41
Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

Hey 👋 . As requested, I gave it a stab at reviewing the PR!

I'm missing some context on this code, in particular it was hard to determine which methods were performance-critical and which were used only for setup/testing/etc off the critical path.

I wonder if it's worth documenting and/or reflecting that in the method names.

I saw the benchmarks in JIRA -- I guess the important part is that ThreadFilterBenchmark is faster? May be worth posting them here too, to give a bit more context.

Comment on lines 386 to 440
extern "C" DLLEXPORT jlong JNICALL
Java_com_datadoghq_profiler_JavaProfiler_tscFrequency0(JNIEnv *env,
jobject unused) {
jclass unused) {
return TSC::frequency();
}

extern "C" DLLEXPORT jlong JNICALL
JavaCritical_com_datadoghq_profiler_JavaProfiler_tscFrequency0() {
Copy link
Member

Choose a reason for hiding this comment

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

Similar note to init0 -- this value seems to be saved in a static final on the Java side and never called again.

@zhengyu123
Copy link
Contributor Author

Hey 👋 . As requested, I gave it a stab at reviewing the PR!

I'm missing some context on this code, in particular it was hard to determine which methods were performance-critical and which were used only for setup/testing/etc off the critical path.

I wonder if it's worth documenting and/or reflecting that in the method names.

I saw the benchmarks in JIRA -- I guess the important part is that ThreadFilterBenchmark is faster? May be worth posting them here too, to give a bit more context.

ThreadFilter methods are performance critical. However, given the simplicity of JavaCritical variants, it does not hurt to add them for none performance critical ones.

@ivoanjo
Copy link
Member

ivoanjo commented Oct 29, 2025

However, given the simplicity of JavaCritical variants, it does not hurt to add them for none performance critical ones.

Hmm... I'll be honest and say that I don't think this is the way to go. Specifically:

  1. Adding JavaCritical variants means more code + more maintenance for it generically. We need to remember to always keep the copy-pasted stuff up-to-date.
  2. It makes it look like those methods are performance-sensitive, which they aren't, so it communicates a weird intent.
  3. If we ever want to refactor some of those methods, we're now constrained by existence of the JavaCritical variant. What happens if it can't be a JavaCritical anymore because we'd like to pass in an object? It may not be clear for many of them we could trivially remove the JavaCritical variant and then change the method signature.

Can I maybe convince you to revisit your approach here? 😄 😉 👀

@zhengyu123
Copy link
Contributor Author

However, given the simplicity of JavaCritical variants, it does not hurt to add them for none performance critical ones.

Hmm... I'll be honest and say that I don't think this is the way to go. Specifically:

  1. Adding JavaCritical variants means more code + more maintenance for it generically. We need to remember to always keep the copy-pasted stuff up-to-date.
  2. It makes it look like those methods are performance-sensitive, which they aren't, so it communicates a weird intent.
  3. If we ever want to refactor some of those methods, we're now constrained by existence of the JavaCritical variant. What happens if it can't be a JavaCritical anymore because we'd like to pass in an object? It may not be clear for many of them we could trivially remove the JavaCritical variant and then change the method signature.

Can I maybe convince you to revisit your approach here? 😄 😉 👀

I am bit confused by your comments - Are you suggesting not to introduce JavaCritical variants? or to remove none performance critical ones.

@ivoanjo
Copy link
Member

ivoanjo commented Oct 29, 2025

Are you suggesting not to introduce JavaCritical variants? or to remove none performance critical ones.

The latter, indeed: I am suggesting to remove the non-performance critical.

TL;DR version of my point is: I think the trade-off is worth it 👍 for the ones that give us performance, but not worth it for the ones that don't 👎 .

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 wall]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes wall wall
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 15 metrics, 23 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 alloc]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes alloc alloc
wall off off

Summary

Found 0 performance improvements and 1 performance regressions! Performance is the same for 14 metrics, 23 unstable metrics.

scenario Δ mean execution_time Δ mean rss
scenario:renaissance:philosophers worse
[+212.536ms; +1115.464ms] or [+1.653%; +8.675%]
unstable
[-504.838MB; +507.589MB] or [-51.563%; +51.844%]

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 cpu]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes cpu cpu
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 15 metrics, 23 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 cpu,wall,alloc,memleak]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes cpu,wall,alloc,memleak cpu,wall,alloc,memleak
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 15 metrics, 23 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 memleak]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes memleak memleak
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 16 metrics, 22 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 cpu]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes cpu cpu
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 17 metrics, 21 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 memleak,alloc]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes memleak,alloc memleak,alloc
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 14 metrics, 24 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [x86_64 cpu,wall]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes cpu,wall cpu,wall
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 14 metrics, 24 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 memleak]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes memleak memleak
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 17 metrics, 21 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 wall]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes wall wall
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 16 metrics, 22 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 alloc]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes alloc alloc
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 17 metrics, 21 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 cpu,wall,alloc,memleak]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes cpu,wall,alloc,memleak cpu,wall,alloc,memleak
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 17 metrics, 21 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 cpu,wall]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc off off
cpu on on
iterations 5 5
java "11.0.28" "11.0.28"
memleak off off
modes cpu,wall cpu,wall
wall on on

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 16 metrics, 22 unstable metrics.

@pr-commenter
Copy link

pr-commenter bot commented Oct 29, 2025

Benchmarks [aarch64 memleak,alloc]

Parameters

Baseline Candidate
config baseline candidate
ddprof 1.34.0 1.34.0-critical_natives-SNAPSHOT
See matching parameters
Baseline Candidate
alloc on on
cpu off off
iterations 5 5
java "11.0.28" "11.0.28"
memleak on on
modes memleak,alloc memleak,alloc
wall off off

Summary

Found 0 performance improvements and 0 performance regressions! Performance is the same for 16 metrics, 22 unstable metrics.

Copy link
Member

@ivoanjo ivoanjo left a comment

Choose a reason for hiding this comment

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

👍 Looks reasonable! I'd still strongly recommend being a lot more explicit about the ARM64 workaround code, so it's extremely clear for future maintainers why it exists (and when we can get rid of it)

Comment on lines 134 to +135
extern "C" DLLEXPORT void JNICALL
Java_com_datadoghq_profiler_JavaProfiler_filterThreadAdd0(JNIEnv *env,
jobject unused) {
JavaCritical_com_datadoghq_profiler_JavaProfiler_filterThreadAdd0() {
Copy link
Member

Choose a reason for hiding this comment

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

Minor: Should we maybe declare these as inline to softly suggest to the compiler that Java_com_datadoghq_profiler_JavaProfiler_filterThreadAdd0 should inline this, not call into it?

(Or does that not work very well anyway?)

Comment on lines +102 to +111
void VMStructs_::initCriticalJNINatives() {
#ifdef __aarch64__
// aarch64 does not support CriticalJNINatives
JVMFlag* flag = JVMFlag::find("CriticalJNINatives", {JVMFlag::Type::Bool});
if (flag != nullptr && flag->get()) {
flag->set(0);
}
#endif // __aarch64__
}

Copy link
Member

Choose a reason for hiding this comment

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

I still think we should have better documentation here of:

  • Why is this needed (work around JDK 8 bug on ... )
  • What happens if this is not here

"// aarch64 does not support CriticalJNINatives" I'm not sure will be enough for someone 1/2/n years from now to understand why this was added.

Bonus points for reflecting this into the method name e.g. installWorkaroundForJdk8ArmCrash (or something similarly descriptive) would be a good way of conveying some of this information :)

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.

3 participants