Skip to content

Commit

Permalink
Use ConcurrentHashMap for BlazeInterners#newStrongInterner.
Browse files Browse the repository at this point in the history
Offers faster lookups than the Guava interner. Thought of this while reviewing #23638.

PiperOrigin-RevId: 675961107
Change-Id: I3045202209fdf0d9c70959e2432c5fbf55f2f3d7
  • Loading branch information
justinhorvitz authored and copybara-github committed Sep 18, 2024
1 parent 4607ad4 commit a345cda
Showing 1 changed file with 20 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,12 @@
// limitations under the License.
package com.google.devtools.build.lib.concurrent;

import static com.google.common.base.MoreObjects.firstNonNull;

import com.google.common.collect.Interner;
import com.google.common.collect.Interners;
import com.google.common.collect.Interners.InternerBuilder;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/** Wrapper around {@link Interners}, with Blaze-specific predetermined concurrency levels. */
public class BlazeInterners {
Expand All @@ -31,22 +34,31 @@ public static int concurrencyLevel() {
return CONCURRENCY_LEVEL;
}

private static InternerBuilder setConcurrencyLevel(InternerBuilder builder) {
return builder.concurrencyLevel(CONCURRENCY_LEVEL);
}

/**
* Creates an interner which retains a weak reference to each instance it has interned.
*
* <p>It is preferred to use {@code SkyKey#SkyKeyInterner} instead for interning {@code SkyKey}
* types.
*/
public static <T> Interner<T> newWeakInterner() {
return setConcurrencyLevel(Interners.newBuilder().weak()).build();
return Interners.newBuilder().concurrencyLevel(CONCURRENCY_LEVEL).weak().build();
}

public static <T> Interner<T> newStrongInterner() {
return setConcurrencyLevel(Interners.newBuilder().strong()).build();
return new StrongInterner<>();
}
}

/**
* Interner based on {@link ConcurrentHashMap}, which offers faster lookups than Guava's strong
* interner.
*/
private static final class StrongInterner<T> implements Interner<T> {
private final Map<T, T> map = new ConcurrentHashMap<>(CONCURRENCY_LEVEL);

@Override
public T intern(T sample) {
T existing = map.putIfAbsent(sample, sample);
return firstNonNull(existing, sample);
}
}
}

0 comments on commit a345cda

Please sign in to comment.