I analyzed the performance of Thread.setName() in response to a customer workload running Cassandra, where Thread.setName() showed up (mostly because of rather pathetic use of setName() from Cassanda *sigh*).
Profiling showed that most time (around 75%) is spent in the actual syscall, so there are limits on what we can do. There is some fixed overheads like the cost for synchronized, and also some costs that scale with the length of the name, most importantly the UTF8 conversion. I implemented the following improvements: - Removed synchronized from setName(), as suggested by some folks in the JBS issue. This saves ~15 nanoseconds. Not sure if the method could be called contended by Cassandra, if so, the savings might be much larger. - Almost all thread names are Latin1/ASCII, and there is no need to convert to UTF8 in that case. Also, the various OS APIs to set the thread name don't even seem to specify the character encoding. Avoiding the UTF8 conversion brings down the length-dependent costs. In many cases we can also pass down the backing array of the string and avoid copying. - When the name doesn't change, we can skip updating the native name, which makes setName() almost a no-op. - For truncating the name on Linux to 16 chars, instead of using snprintf with a pattern, we can simply stitch together the name directly (first 7 chars, last 6 chars, 2 dots in between), this saves ~100ns. In the end, we bring down performance for the small cases by ~7%, longer names by ~20% and completely removed the conversion overhead that primarily affected longer names. | Benchmark | (length) | Baseline (ns/op) | Optimized (ns/op) | Change | |---------------|----------|------------------:|-------------------:|--------:| | setName | 1 | 602.3 ± 2.0 | 561.9 ± 1.5 | -6.7% | | setName | 4 | 605.9 ± 2.1 | 570.2 ± 1.2 | -5.9% | | setName | 15 | 617.1 ± 2.7 | 570.4 ± 2.8 | -7.6% | | setName | 16 | 712.1 ± 6.0 | 569.4 ± 2.7 | -20.0% | | setName | 50 | 757.9 ± 5.2 | 566.3 ± 4.6 | -25.3% | | setName | 200 | 986.2 ± 2.7 | 569.9 ± 4.9 | -42.2% | | setNameSame | 1 | — | 7.4 ± 0.0 | — | | setNameSame | 4 | — | 7.4 ± 0.0 | — | | setNameSame | 15 | — | 7.4 ± 0.0 | — | | setNameSame | 16 | — | 7.4 ± 0.0 | — | | setNameSame | 50 | — | 7.4 ± 0.0 | — | | setNameSame | 200 | — | 7.4 ± 0.0 | — | Testing: - [x] tier1 - [ ] tier2 The failing GHA test in langtools seems unrelated. ------------- Commit messages: - 8373554: Improve performance of Thread.setName() Changes: https://git.openjdk.org/jdk/pull/30374/files Webrev: https://webrevs.openjdk.org/?repo=jdk&pr=30374&range=00 Issue: https://bugs.openjdk.org/browse/JDK-8373554 Stats: 124 lines in 8 files changed: 106 ins; 0 del; 18 mod Patch: https://git.openjdk.org/jdk/pull/30374.diff Fetch: git fetch https://git.openjdk.org/jdk.git pull/30374/head:pull/30374 PR: https://git.openjdk.org/jdk/pull/30374
