Skip to content

Conversation

trask
Copy link
Member

@trask trask commented Sep 23, 2025

The delayMs=0 tests seem to have a lot of variance, I've seen them fluctuate in both directions.

Java 8 Results

BatchSpanProcessorBenchmark.export Results

Test Configuration Main Branch (ops/s) PR Branch (ops/s) Difference % Change
delayMs=0, spanCount=1000 2,902.557 ±659.449 2,677.476 ±481.106 -225.081 -7.8%
delayMs=0, spanCount=2000 1,180.198 ±153.058 1,487.399 ±446.232 +307.202 +26.0%
delayMs=0, spanCount=5000 459.718 ±26.793 495.353 ±157.615 +35.635 +7.8%
delayMs=1, spanCount=1000 852.660 ±16.069 840.142 ±9.107 -12.519 -1.5%
delayMs=1, spanCount=2000 848.187 ±14.081 860.653 ±5.051 +12.466 +1.5%
delayMs=1, spanCount=5000 844.831 ±6.976 842.294 ±8.436 -2.537 -0.3%
delayMs=5, spanCount=1000 192.646 ±1.071 191.746 ±0.166 -0.900 -0.5%
delayMs=5, spanCount=2000 191.869 ±0.669 191.323 ±0.142 -0.545 -0.3%
delayMs=5, spanCount=5000 192.395 ±0.587 191.904 ±0.155 -0.491 -0.3%
delayMs=1 6,495.065 ±21.094 6,494.511 ±22.144 -0.553 -0.0%
delayMs=1 12,990.008 ±35.990 12,989.210 ±37.926 -0.798 -0.0%
delayMs=1 32,455.636 ±85.836 32,451.134 ±107.924 -4.502 -0.0%
delayMs=1 64,677.531 ±723.640 64,771.413 ±375.335 +93.882 +0.1%
delayMs=1 128,407.393 ±1000.361 128,357.234 ±821.825 -50.159 -0.0%

Multi-threading Benchmark Results

Benchmark Main Branch (ops/s) PR Branch (ops/s) Difference % Change
export_01Thread (delayMs=1) 6,495.065 ±21.094 6,494.511 ±22.144 -0.553 -0.01%
export_02Thread (delayMs=1) 12,990.008 ±35.990 12,989.210 ±37.926 -0.798 -0.01%
export_05Thread (delayMs=1) 32,455.636 ±85.836 32,451.134 ±107.924 -4.502 -0.01%
export_10Thread (delayMs=1) 64,677.531 ±723.640 64,771.413 ±375.335 +93.882 +0.15%
export_20Thread (delayMs=1) 128,407.393 ±1000.361 128,357.234 ±821.825 -50.159 -0.04%

Java 17 Results

BatchSpanProcessorBenchmark.export Results

Test Configuration Main Branch (ops/s) PR Branch (ops/s) Difference % Change
delayMs=0, spanCount=1000 3,679.256 ±790.480 3,189.126 ±805.833 -490.130 -13.3%
delayMs=0, spanCount=2000 1,469.195 ±253.238 1,450.430 ±535.113 -18.765 -1.3%
delayMs=0, spanCount=5000 479.057 ±117.375 741.342 ±215.326 +262.285 +54.8%
delayMs=1, spanCount=1000 837.619 ±15.090 846.656 ±16.155 +9.037 +1.1%
delayMs=1, spanCount=2000 846.046 ±9.929 835.721 ±5.460 -10.325 -1.2%
delayMs=1, spanCount=5000 847.892 ±5.528 847.507 ±20.862 -0.386 -0.0%
delayMs=5, spanCount=1000 191.873 ±1.272 191.185 ±0.674 -0.687 -0.4%
delayMs=5, spanCount=2000 191.765 ±1.446 191.489 ±1.188 -0.276 -0.1%
delayMs=5, spanCount=5000 191.484 ±1.672 191.150 ±1.526 -0.334 -0.2%
delayMs=1 6,495.296 ±26.959 6,495.014 ±28.248 -0.283 -0.0%
delayMs=1 12,986.684 ±69.585 12,984.156 ±67.239 -2.528 -0.0%
delayMs=1 32,450.418 ±140.282 32,451.362 ±153.871 +0.944 +0.0%
delayMs=1 64,835.326 ±419.437 64,845.004 ±482.903 +9.678 +0.0%
delayMs=1 128,302.847 ±1380.143 128,207.056 ±1418.474 -95.792 -0.1%

Multi-threading Benchmark Results

Benchmark Main Branch (ops/s) PR Branch (ops/s) Difference % Change
export_01Thread (delayMs=1) 6,495.296 ±26.959 6,495.014 ±28.248 -0.283 -0.00%
export_02Thread (delayMs=1) 12,986.684 ±69.585 12,984.156 ±67.239 -2.528 -0.02%
export_05Thread (delayMs=1) 32,450.418 ±140.282 32,451.362 ±153.871 +0.944 +0.00%
export_10Thread (delayMs=1) 64,835.326 ±419.437 64,845.004 ±482.903 +9.678 +0.01%
export_20Thread (delayMs=1) 128,302.847 ±1380.143 128,207.056 ±1418.474 -95.792 -0.07%

Java 24 Results

BatchSpanProcessorBenchmark.export Results

Test Configuration Main Branch (ops/s) PR Branch (ops/s) Difference % Change
delayMs=0, spanCount=1000 3,109.623 ±826.821 3,443.793 ±1197.910 +334.170 +10.7%
delayMs=0, spanCount=2000 1,326.157 ±199.990 1,155.285 ±61.366 -170.872 -12.9%
delayMs=0, spanCount=5000 622.792 ±40.550 511.532 ±87.939 -111.260 -17.9%
delayMs=1, spanCount=1000 845.640 ±2.345 853.888 ±15.808 +8.247 +1.0%
delayMs=1, spanCount=2000 842.823 ±2.052 839.436 ±1.850 -3.387 -0.4%
delayMs=1, spanCount=5000 840.577 ±2.887 836.613 ±8.446 -3.964 -0.5%
delayMs=5, spanCount=1000 191.576 ±1.589 191.705 ±1.989 +0.129 +0.1%
delayMs=5, spanCount=2000 191.105 ±1.219 190.458 ±1.547 -0.647 -0.3%
delayMs=5, spanCount=5000 191.087 ±1.460 191.182 ±1.319 +0.095 +0.0%
delayMs=1 6,494.026 ±32.405 6,494.527 ±25.915 +0.501 +0.0%
delayMs=1 12,986.492 ±53.347 12,986.381 ±56.660 -0.112 -0.0%
delayMs=1 32,455.839 ±167.412 32,458.205 ±160.005 +2.366 +0.0%
delayMs=1 64,832.548 ±242.614 64,887.898 ±320.588 +55.350 +0.1%
delayMs=1 127,782.627 ±237.159 128,444.628 ±637.934 +662.002 +0.5%

Multi-threading Benchmark Results

Benchmark Main Branch (ops/s) PR Branch (ops/s) Difference % Change
export_01Thread (delayMs=1) 6,494.026 ±32.405 6,494.527 ±25.915 +0.501 +0.01%
export_02Thread (delayMs=1) 12,986.492 ±53.347 12,986.381 ±56.660 -0.112 -0.00%
export_05Thread (delayMs=1) 32,455.839 ±167.412 32,458.205 ±160.005 +2.366 +0.01%
export_10Thread (delayMs=1) 64,832.548 ±242.614 64,887.898 ±320.588 +55.350 +0.09%
export_20Thread (delayMs=1) 127,782.627 ±237.159 128,444.628 ±637.934 +662.002 +0.52%

@trask trask force-pushed the proactively-avoid-unsafe-warning branch from 661360e to a256eb9 Compare September 23, 2025 14:41
@trask trask force-pushed the proactively-avoid-unsafe-warning branch from a256eb9 to 25cdac8 Compare September 23, 2025 17:30
Copy link

codecov bot commented Sep 23, 2025

Codecov Report

❌ Patch coverage is 66.66667% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.16%. Comparing base (1e763b2) to head (1e86329).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
...a/io/opentelemetry/sdk/trace/internal/JcTools.java 66.66% 1 Missing ⚠️

❌ Your patch status has failed because the patch coverage (66.66%) is below the target coverage (80.00%). You can increase the patch coverage or adjust the target coverage.

Additional details and impacted files
@@             Coverage Diff              @@
##               main    #7691      +/-   ##
============================================
+ Coverage     90.12%   90.16%   +0.03%     
+ Complexity     7187     7184       -3     
============================================
  Files           814      814              
  Lines         21700    21684      -16     
  Branches       2123     2121       -2     
============================================
- Hits          19557    19551       -6     
+ Misses         1477     1466      -11     
- Partials        666      667       +1     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@trask trask force-pushed the proactively-avoid-unsafe-warning branch 7 times, most recently from 7eb55dd to cf78fd7 Compare September 23, 2025 22:38
// or a security manager preventing access to Unsafe is installed.
return new ArrayBlockingQueue<>(capacity);
}
return new MpscAtomicArrayQueue<>(capacity);
Copy link
Member Author

@trask trask Sep 24, 2025

Choose a reason for hiding this comment

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

key insight here was from JCTools/JCTools#395 (comment):

Users can use atomic queues as an Unsafe free alternative (where possible)

I originally only used this implementation on Java 22+, just to avoid triggering the Unsafe warning

but given that the benchmarks look fine, I think it would be ok to go straight to this implementation in all cases and simplify things

Copy link
Member

Choose a reason for hiding this comment

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

What's the difference between MpscArrayQueue and MpscAtomicArrayQueue?

Copy link
Member Author

Choose a reason for hiding this comment

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

@trask trask force-pushed the proactively-avoid-unsafe-warning branch 2 times, most recently from 2c01b46 to 5ad4670 Compare September 24, 2025 14:46
@trask trask force-pushed the proactively-avoid-unsafe-warning branch from 5ad4670 to 1e86329 Compare September 24, 2025 14:47
.isInstanceOfSatisfying(
Queue.class, queue -> assertThat(JcTools.capacity(queue)).isEqualTo(2));
ArrayBlockingQueue.class,
queue -> assertThat(queue.remainingCapacity()).isEqualTo(2));
Copy link
Member Author

@trask trask Sep 24, 2025

Choose a reason for hiding this comment

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

BatchLogRecordProcessor uses ArrayBlockingQueue, so this test abstraction wasn't needed (probably a copy paste from similar test for BatchSpanProcessor):

new ArrayBlockingQueue<>(maxQueueSize)); // TODO: use JcTools.newFixedSizeQueue(..)

ArrayList<String> batch = new ArrayList<>(10);

@Test
void drain_ArrayBlockingQueue() {
Copy link
Member Author

Choose a reason for hiding this comment

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

no need to test ArrayBlockingQueue anymore with this change

@trask trask marked this pull request as ready for review September 24, 2025 14:52
@trask trask requested a review from a team as a code owner September 24, 2025 14:52
AccessController.doPrivileged(
(PrivilegedAction<Queue<Object>>) () -> JcTools.newFixedSizeQueue(10));
assertThat(queue).isInstanceOf(ArrayBlockingQueue.class);
assertThat(queue).isInstanceOf(MpscAtomicArrayQueue.class);
Copy link
Member

Choose a reason for hiding this comment

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

Was going to say that this test is no longer relevant. But I suppose its still good to assert htat MpscAtomicArrayQueue doesn't rely on unsafe.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, though I think we could revisit and probably delete it after #7683

Copy link
Member

@jack-berg jack-berg left a comment

Choose a reason for hiding this comment

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

This looks good to me, but I'll defer to @jkwatson who was around for the original decision to use MpscArrayQueue and might know more about the original motivation and implementation details.

@jkwatson
Copy link
Contributor

This looks good to me, but I'll defer to @jkwatson who was around for the original decision to use MpscArrayQueue and might know more about the original motivation and implementation details.

whew. That was a while ago. I think it was only performance related, so if we can get the same perf without an Unsafe-based implementation, then no reason not to do it.

@trask
Copy link
Member Author

trask commented Sep 25, 2025

@open-telemetry/android-approvers can we verify this PR on android, since no longer falling back to ArrayBlockingQueue and using safe version of JCTools queue?

Copy link
Contributor

@LikeTheSalad LikeTheSalad left a comment

Choose a reason for hiding this comment

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

@open-telemetry/android-approvers can we verify this PR on android, since no longer falling back to ArrayBlockingQueue and using safe version of JCTools queue?

I've just checked by running a local release with these changes on an Android device with API level 21 and using a BatchSpanProcessor, which seems to be where the changed methods are used. I didn't see any errors.

I also confirmed what I mentioned here that animalsniffer only checks local classes, but not the classes inside dependencies. So far, it doesn't seem that any dependency is causing issues. In any case, if we think we're planning on relying on several more dependencies in the future, it is probably worth checking if the animalsniffer task can get configured to also verify classes from them.

@jkwatson jkwatson merged commit 0426932 into open-telemetry:main Sep 26, 2025
28 of 29 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants