mirror of https://github.com/grpc/grpc-java.git
core: allow attributes to be built multiple times
This commit is contained in:
parent
401066ada3
commit
291f17059e
|
|
@ -0,0 +1,80 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2017, gRPC Authors All rights reserved.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package io.grpc;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Benchmark;
|
||||||
|
import org.openjdk.jmh.annotations.BenchmarkMode;
|
||||||
|
import org.openjdk.jmh.annotations.Mode;
|
||||||
|
import org.openjdk.jmh.annotations.OutputTimeUnit;
|
||||||
|
import org.openjdk.jmh.annotations.Param;
|
||||||
|
import org.openjdk.jmh.annotations.Scope;
|
||||||
|
import org.openjdk.jmh.annotations.Setup;
|
||||||
|
import org.openjdk.jmh.annotations.State;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Javadoc.
|
||||||
|
*/
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
public class AttributesBenchmark {
|
||||||
|
|
||||||
|
public Attributes base = Attributes.EMPTY;
|
||||||
|
|
||||||
|
public Attributes.Key<Object>[] keys;
|
||||||
|
public Attributes withValue = base;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Javadoc.
|
||||||
|
*/
|
||||||
|
@Setup
|
||||||
|
@SuppressWarnings({"unchecked", "rawtypes"})
|
||||||
|
public void setUp() {
|
||||||
|
keys = new Attributes.Key[iterations];
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
keys[i] = Attributes.Key.of("any");
|
||||||
|
withValue = Attributes.newBuilder(withValue).set(keys[i], "yes").build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Param({"1", "2", "10"})
|
||||||
|
public int iterations;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Javadoc.
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.SampleTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
public Attributes chain() {
|
||||||
|
Attributes attr = base;
|
||||||
|
for (int i = 0; i < iterations; i++) {
|
||||||
|
attr = Attributes.newBuilder(attr).set(keys[i], new Object()).build();
|
||||||
|
}
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Javadoc.
|
||||||
|
*/
|
||||||
|
@Benchmark
|
||||||
|
@BenchmarkMode(Mode.SampleTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.NANOSECONDS)
|
||||||
|
public Object lookup() {
|
||||||
|
return withValue.get(keys[0]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -16,10 +16,13 @@
|
||||||
|
|
||||||
package io.grpc;
|
package io.grpc;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import com.google.common.base.Objects;
|
import com.google.common.base.Objects;
|
||||||
import com.google.common.base.Preconditions;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.IdentityHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.concurrent.Immutable;
|
import javax.annotation.concurrent.Immutable;
|
||||||
|
|
@ -31,11 +34,13 @@ import javax.annotation.concurrent.Immutable;
|
||||||
@Immutable
|
@Immutable
|
||||||
public final class Attributes {
|
public final class Attributes {
|
||||||
|
|
||||||
private final HashMap<Key<?>, Object> data = new HashMap<Key<?>, Object>();
|
private final Map<Key<?>, Object> data;
|
||||||
|
|
||||||
public static final Attributes EMPTY = new Attributes();
|
public static final Attributes EMPTY = new Attributes(Collections.<Key<?>, Object>emptyMap());
|
||||||
|
|
||||||
private Attributes() {
|
private Attributes(Map<Key<?>, Object> data) {
|
||||||
|
assert data != null;
|
||||||
|
this.data = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -60,14 +65,15 @@ public final class Attributes {
|
||||||
* Create a new builder that is pre-populated with the content from a given container.
|
* Create a new builder that is pre-populated with the content from a given container.
|
||||||
*/
|
*/
|
||||||
public static Builder newBuilder(Attributes base) {
|
public static Builder newBuilder(Attributes base) {
|
||||||
return newBuilder().setAll(base);
|
checkNotNull(base, "base");
|
||||||
|
return new Builder(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new builder.
|
* Create a new builder.
|
||||||
*/
|
*/
|
||||||
public static Builder newBuilder() {
|
public static Builder newBuilder() {
|
||||||
return new Builder();
|
return new Builder(EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -144,30 +150,45 @@ public final class Attributes {
|
||||||
* The helper class to build an Attributes instance.
|
* The helper class to build an Attributes instance.
|
||||||
*/
|
*/
|
||||||
public static final class Builder {
|
public static final class Builder {
|
||||||
private Attributes product;
|
private Attributes base;
|
||||||
|
private Map<Key<?>, Object> newdata;
|
||||||
|
|
||||||
private Builder() {
|
private Builder(Attributes base) {
|
||||||
this.product = new Attributes();
|
assert base != null;
|
||||||
|
this.base = base;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Key<?>, Object> data(int size) {
|
||||||
|
if (newdata == null) {
|
||||||
|
newdata = new IdentityHashMap<Key<?>, Object>(size);
|
||||||
|
}
|
||||||
|
return newdata;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Builder set(Key<T> key, T value) {
|
public <T> Builder set(Key<T> key, T value) {
|
||||||
product.data.put(key, value);
|
data(1).put(key, value);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> Builder setAll(Attributes other) {
|
public <T> Builder setAll(Attributes other) {
|
||||||
product.data.putAll(other.data);
|
data(other.data.size()).putAll(other.data);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Build the attributes. Can only be called once.
|
* Build the attributes.
|
||||||
*/
|
*/
|
||||||
public Attributes build() {
|
public Attributes build() {
|
||||||
Preconditions.checkState(product != null, "Already built");
|
if (newdata != null) {
|
||||||
Attributes result = product;
|
for (Entry<Key<?>, Object> entry : base.data.entrySet()) {
|
||||||
product = null;
|
if (!newdata.containsKey(entry.getKey())) {
|
||||||
return result;
|
newdata.put(entry.getKey(), entry.getValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base = new Attributes(newdata);
|
||||||
|
newdata = null;
|
||||||
|
}
|
||||||
|
return base;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue