-
Notifications
You must be signed in to change notification settings - Fork 6.2k
8263090: Avoid reading volatile fields twice in Locale.getDefault(Category) #2845
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
Conversation
|
👋 Welcome back redestad! A progress list of the required criteria for merging this PR into |
|
Results on the provided, simple microbenchmark Baseline: Patch: |
Webrevs
|
|
@cl4es This change now passes all automated pre-integration checks. ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details. After integration, the commit message for the final commit will be: You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed. At the time when this comment was updated there had been 31 new commits pushed to the
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details. ➡️ To integrate this PR with the above commit message to the |
naotoj
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good.
| if (category == Category.DISPLAY) { | ||
| Locale loc = defaultDisplayLocale; // volatile read | ||
| if (loc == null) { | ||
| loc = getDisplayLocale(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just interesting how did you check that the performance difference is because of volatile read, and not because of replacing of the switch by the "if"?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I started out with this variant, only removing the double volatile reads:
public static Locale getDefault(Locale.Category category) {
// do not synchronize this method - see 4071298
Locale loc;
switch (category) {
case DISPLAY:
loc = defaultDisplayLocale;
if (loc == null) {
synchronized(Locale.class) {
loc = defaultDisplayLocale;
if (loc == null) {
loc = defaultDisplayLocale = initDefault(category);
}
}
}
return loc;
case FORMAT:
loc = defaultFormatLocale;
if (loc == null) {
synchronized(Locale.class) {
loc = defaultFormatLocale;
if (loc == null) {
loc = defaultFormatLocale = initDefault(category);
}
}
}
return loc;
default:
assert false: "Unknown Category";
}
return getDefault();
}
Scores were the same:
Benchmark Mode Cnt Score Error Units
LocaleDefaults.getDefault avgt 5 10.045 ± 0.032 ns/op
LocaleDefaults.getDefaultDisplay avgt 5 11.301 ± 0.053 ns/op
LocaleDefaults.getDefaultFormat avgt 5 11.303 ± 0.054 ns/op
I then refactored and checked that the refactorings were performance neutral.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And it is faster than the final version?
|
If I read the order right your benchmark findings were done before you added the missing synchronized - correct? AFAICS the only unnecessary volatile read is on the return statement and you could fix that without doing the other refactoring. I don't see how introducing an extra method call can aid performance. |
Note that the score for the Display and the Format case were identical, even though one was missing synchronized. I've re-run the benchmarks after the fix and the same applies. The methods will only ever be called during initialization, usually only once. Extracting them to separate methods helps outline initialization code from the hot path. Such outlining is a standard technique to help the JITs do the right thing, for example by ensuring you don't stumble on things like inlining thresholds. |
|
Mailing list message from Claes Redestad on i18n-dev: No, I accidentally posted numbers for an apples to oranges comparison (-t 1 vs -t 4 on the same system). The final version does not differ in performance from this version when comparing like for like. H?mta Outlook f?r Android<https://aka.ms/ghei36> ________________________________ On Sat, 6 Mar 2021 13:34:14 GMT, Claes Redestad <redestad at openjdk.org> wrote:
And it is faster than the final version? ------------- PR: https://git.openjdk.java.net/jdk/pull/2845 |
|
/integrate |
|
Pushed as commit 13625be. |
This patch refactors Locale.getDefault(Category) so that the volatile field holding the Locale is typically only read once. This has a small performance advantage, and might be more robust if initialization is racy.
Progress
Issue
Reviewers
Download
$ git fetch https://git.openjdk.java.net/jdk pull/2845/head:pull/2845$ git checkout pull/2845