8348880: Replace ConcurrentMap with AtomicReferenceArray for ZoneOffset.QUARTER_CACHE

Reviewed-by: naoto, liach
This commit is contained in:
Shaojin Wen 2025-01-30 15:13:13 +00:00
parent fac63d4383
commit 3f8a875497
2 changed files with 29 additions and 7 deletions

View file

@ -1,5 +1,6 @@
/*
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Alibaba Group Holding Limited. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -85,6 +86,7 @@ import java.time.zone.ZoneRules;
import java.util.Objects;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.atomic.AtomicReferenceArray;
import jdk.internal.vm.annotation.Stable;
@ -134,8 +136,10 @@ public final class ZoneOffset
extends ZoneId
implements TemporalAccessor, TemporalAdjuster, Comparable<ZoneOffset>, Serializable {
/** Cache of time-zone offset by offset in seconds. */
private static final ConcurrentMap<Integer, ZoneOffset> SECONDS_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
/** Cache of time-zone offset by offset in quarters. */
private static final int SECONDS_PER_QUARTER = 15 * SECONDS_PER_MINUTE;
private static final AtomicReferenceArray<ZoneOffset> QUARTER_CACHE = new AtomicReferenceArray<>(256);
/** Cache of time-zone offset by ID. */
private static final ConcurrentMap<String, ZoneOffset> ID_CACHE = new ConcurrentHashMap<>(16, 0.75f, 4);
@ -423,12 +427,14 @@ public final class ZoneOffset
if (totalSeconds < -MAX_SECONDS || totalSeconds > MAX_SECONDS) {
throw new DateTimeException("Zone offset not in valid range: -18:00 to +18:00");
}
if (totalSeconds % (15 * SECONDS_PER_MINUTE) == 0) {
Integer totalSecs = totalSeconds;
ZoneOffset result = SECONDS_CACHE.get(totalSecs);
int quarters = totalSeconds / SECONDS_PER_QUARTER;
if (totalSeconds - quarters * SECONDS_PER_QUARTER == 0) {
// quarters range from -72 to 72, & 0xff maps them to 0-72 and 184-255.
int key = quarters & 0xff;
ZoneOffset result = QUARTER_CACHE.getOpaque(key);
if (result == null) {
result = new ZoneOffset(totalSeconds);
var existing = SECONDS_CACHE.putIfAbsent(totalSecs, result);
var existing = QUARTER_CACHE.compareAndExchange(key, null, result);
if (existing != null) {
result = existing;
}