core: Remove com.google.common.collect usages for Android

This reduces the number of methods gRPC brings in by ~450, which is
substantial. Each application will see different numbers though,
depending on their usage and their other dependencies.

A very rough (under) counting for number of methods included because of
gRPC in android-interop-test is 2746, and that is reduced to 2313 (-433)
by this change. That count includes grpc, guava, okhttp, okio, and nano.
The actual reduction of methods is 447, with the discrepency due to
reduction of methods in java.util and java.lang. Of the 433 removed
methods, 377 are from com.google.common.collect and 61 from
com.google.common.base. The removal costed an increase of 5 methods
(total 1671) within io.grpc itself.
This commit is contained in:
Eric Anderson 2016-02-17 10:19:08 -08:00
parent f254fadfbe
commit 656e8ce37f
9 changed files with 100 additions and 57 deletions

View File

@ -1130,16 +1130,11 @@ void GenerateService(const ServiceDescriptor* service,
vars["ServiceDescriptor"] =
"io.grpc.ServiceDescriptor";
vars["AbstractStub"] = "io.grpc.stub.AbstractStub";
vars["ImmutableList"] = "com.google.common.collect.ImmutableList";
vars["Collection"] = "java.util.Collection";
vars["MethodDescriptor"] = "io.grpc.MethodDescriptor";
vars["NanoUtils"] = "io.grpc.protobuf.nano.NanoUtils";
vars["StreamObserver"] = "io.grpc.stub.StreamObserver";
vars["Iterator"] = "java.util.Iterator";
vars["Map"] = "java.util.Map";
vars["TimeUnit"] = "java.util.concurrent.TimeUnit";
vars["Generated"] = "javax.annotation.Generated";
vars["Immutable"] = "javax.annotation.concurrent.Immutable";
vars["ListenableFuture"] =
"com.google.common.util.concurrent.ListenableFuture";
vars["ExperimentalApi"] = "io.grpc.ExperimentalApi";

View File

@ -36,14 +36,13 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Preconditions;
import com.google.common.collect.Iterables;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.BitSet;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
@ -202,19 +201,12 @@ public final class Metadata {
* parsed as T or null if there are none. The iterator is not guaranteed to be "live." It may or
* may not be accurate if Metadata is mutated.
*/
public <T> Iterable<T> getAll(final Key<T> key) {
public <T> Iterable<T> getAll(Key<T> key) {
if (containsKey(key)) {
/* This is unmodifiable currently, but could be made to support remove() in the future. If
* removal support is added, the {@link #storeCount} variable needs to be updated
* appropriately. */
return Iterables.unmodifiableIterable(Iterables.transform(
store.get(key.name()),
new Function<MetadataEntry, T>() {
@Override
public T apply(MetadataEntry entry) {
return entry.getParsed(key);
}
}));
return new ValueIterable<T>(key, store.get(key.name()));
}
return null;
}
@ -270,18 +262,13 @@ public final class Metadata {
/**
* Remove all values for the given key. If there were no values, {@code null} is returned.
*/
public <T> Iterable<T> removeAll(final Key<T> key) {
public <T> Iterable<T> removeAll(Key<T> key) {
List<MetadataEntry> values = store.remove(key.name());
if (values == null) {
return null;
}
storeCount -= values.size();
return Iterables.transform(values, new Function<MetadataEntry, T>() {
@Override
public T apply(MetadataEntry metadataEntry) {
return metadataEntry.getParsed(key);
}
});
return new ValueIterable<T>(key, values);
}
/**
@ -694,4 +681,35 @@ public final class Metadata {
}
}
}
private static class ValueIterable<T> implements Iterable<T> {
private final Key<T> key;
private final Iterable<MetadataEntry> entries;
public ValueIterable(Key<T> key, Iterable<MetadataEntry> entries) {
this.key = key;
this.entries = entries;
}
@Override
public Iterator<T> iterator() {
final Iterator<MetadataEntry> iterator = entries.iterator();
class ValueIterator implements Iterator<T> {
@Override public boolean hasNext() {
return iterator.hasNext();
}
@Override public T next() {
return iterator.next().getParsed(key);
}
@Override public void remove() {
// Not implemented to not need to conditionally update {@link #storeCount}.
throw new UnsupportedOperationException();
}
}
return new ValueIterator();
}
}
}

View File

@ -35,10 +35,9 @@ import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import com.google.common.collect.ImmutableMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -55,12 +54,13 @@ public final class ServerServiceDefinition {
}
private final ServiceDescriptor serviceDescriptor;
private final ImmutableMap<String, ServerMethodDefinition<?, ?>> methods;
private final Map<String, ServerMethodDefinition<?, ?>> methods;
private ServerServiceDefinition(
ServiceDescriptor serviceDescriptor, Map<String, ServerMethodDefinition<?, ?>> methods) {
this.serviceDescriptor = checkNotNull(serviceDescriptor, "serviceDescriptor");
this.methods = ImmutableMap.copyOf(methods);
this.methods = Collections.unmodifiableMap(
new HashMap<String, ServerMethodDefinition<?, ?>>(methods));
}
/**

View File

@ -38,7 +38,6 @@ import com.google.common.base.Preconditions;
import com.google.common.base.Splitter;
import com.google.common.base.Stopwatch;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
import com.google.common.util.concurrent.MoreExecutors;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
@ -50,6 +49,12 @@ import java.lang.reflect.Method;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.AbstractMap.SimpleImmutableEntry;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@ -485,23 +490,32 @@ public final class GrpcUtil {
@VisibleForTesting
static class TimeoutMarshaller implements Metadata.AsciiMarshaller<Long> {
// ImmutableMap's have consistent iteration order.
private static final ImmutableMap<Character, TimeUnit> UNITS =
ImmutableMap.<Character, TimeUnit>builder()
.put('n', TimeUnit.NANOSECONDS)
.put('u', TimeUnit.MICROSECONDS)
.put('m', TimeUnit.MILLISECONDS)
.put('S', TimeUnit.SECONDS)
.put('M', TimeUnit.MINUTES)
.put('H', TimeUnit.HOURS)
.build();
@SuppressWarnings("unchecked") // asList uses an array which doesn't handle generics
private static final List<Map.Entry<Character, TimeUnit>> SERIALIZE_ORDER
= Collections.unmodifiableList(Arrays.<Entry<Character, TimeUnit>>asList(
new SimpleImmutableEntry<Character, TimeUnit>('n', TimeUnit.NANOSECONDS),
new SimpleImmutableEntry<Character, TimeUnit>('u', TimeUnit.MICROSECONDS),
new SimpleImmutableEntry<Character, TimeUnit>('m', TimeUnit.MILLISECONDS),
new SimpleImmutableEntry<Character, TimeUnit>('S', TimeUnit.SECONDS),
new SimpleImmutableEntry<Character, TimeUnit>('M', TimeUnit.MINUTES),
new SimpleImmutableEntry<Character, TimeUnit>('H', TimeUnit.HOURS)));
private static final Map<Character, TimeUnit> UNITS = createUnits();
private static Map<Character, TimeUnit> createUnits() {
Map<Character, TimeUnit> units = new HashMap<Character, TimeUnit>();
for (Entry<Character, TimeUnit> unit : SERIALIZE_ORDER) {
units.put(unit.getKey(), unit.getValue());
}
return Collections.unmodifiableMap(units);
}
@Override
public String toAsciiString(Long timeoutNanos) {
checkArgument(timeoutNanos >= 0, "Negative timeout");
// the smallest integer with 9 digits
int cutoff = 100000000;
for (Entry<Character, TimeUnit> unit : UNITS.entrySet()) {
for (Entry<Character, TimeUnit> unit : SERIALIZE_ORDER) {
long timeout = unit.getValue().convert(timeoutNanos, TimeUnit.NANOSECONDS);
if (timeout < cutoff) {
return Long.toString(timeout) + unit.getKey();

View File

@ -32,10 +32,10 @@
package io.grpc.internal;
import com.google.common.base.Stopwatch;
import com.google.common.collect.Maps;
import io.grpc.internal.ClientTransport.PingCallback;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
@ -68,7 +68,8 @@ public class Http2Ping {
/**
* The registered callbacks and the executor used to invoke them.
*/
@GuardedBy("this") private Map<PingCallback, Executor> callbacks = Maps.newLinkedHashMap();
@GuardedBy("this") private Map<PingCallback, Executor> callbacks
= new LinkedHashMap<PingCallback, Executor>();
/**
* False until the operation completes, either successfully (other side sent acknowledgement) or

View File

@ -31,18 +31,19 @@
package io.grpc.internal;
import com.google.common.collect.ImmutableMap;
import io.grpc.ServerMethodDefinition;
import io.grpc.ServerServiceDefinition;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
final class InternalHandlerRegistry {
private final ImmutableMap<String, ServerMethodDefinition<?, ?>> methods;
private final Map<String, ServerMethodDefinition<?, ?>> methods;
private InternalHandlerRegistry(ImmutableMap<String, ServerMethodDefinition<?, ?>> methods) {
private InternalHandlerRegistry(Map<String, ServerMethodDefinition<?, ?>> methods) {
this.methods = methods;
}
@ -62,14 +63,14 @@ final class InternalHandlerRegistry {
}
InternalHandlerRegistry build() {
ImmutableMap.Builder<String, ServerMethodDefinition<?, ?>> mapBuilder =
ImmutableMap.builder();
Map<String, ServerMethodDefinition<?, ?>> map =
new HashMap<String, ServerMethodDefinition<?, ?>>();
for (ServerServiceDefinition service : services.values()) {
for (ServerMethodDefinition<?, ?> method : service.getMethods()) {
mapBuilder.put(method.getMethodDescriptor().getFullMethodName(), method);
map.put(method.getMethodDescriptor().getFullMethodName(), method);
}
}
return new InternalHandlerRegistry(mapBuilder.build());
return new InternalHandlerRegistry(Collections.unmodifiableMap(map));
}
}
}

View File

@ -32,7 +32,6 @@
package io.grpc.internal;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Iterators;
import io.grpc.EquivalentAddressGroup;
@ -40,7 +39,9 @@ import io.grpc.Status;
import io.grpc.TransportManager;
import java.net.SocketAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@ -95,8 +96,7 @@ public class RoundRobinServerList<T> {
@NotThreadSafe
public static class Builder<T> {
private final ImmutableList.Builder<EquivalentAddressGroup> listBuilder =
ImmutableList.builder();
private final List<EquivalentAddressGroup> list = new ArrayList<EquivalentAddressGroup>();
private final TransportManager<T> tm;
public Builder(TransportManager<T> tm) {
@ -107,7 +107,7 @@ public class RoundRobinServerList<T> {
* Adds a server to the list, or {@code null} for a drop entry.
*/
public Builder<T> addSocketAddress(@Nullable SocketAddress address) {
listBuilder.add(new EquivalentAddressGroup(address));
list.add(new EquivalentAddressGroup(address));
return this;
}
@ -117,7 +117,7 @@ public class RoundRobinServerList<T> {
* @param addresses the addresses to add
*/
public Builder<T> add(EquivalentAddressGroup addresses) {
listBuilder.add(addresses);
list.add(addresses);
return this;
}
@ -127,12 +127,13 @@ public class RoundRobinServerList<T> {
* @param addresses the list of addresses group.
*/
public Builder<T> addAll(Collection<EquivalentAddressGroup> addresses) {
listBuilder.addAll(addresses);
list.addAll(addresses);
return this;
}
public RoundRobinServerList<T> build() {
return new RoundRobinServerList<T>(tm, listBuilder.build());
return new RoundRobinServerList<T>(tm,
Collections.unmodifiableList(new ArrayList<EquivalentAddressGroup>(list)));
}
}
}

View File

@ -114,6 +114,18 @@ public class MetadataTest {
assertEquals(null, metadata.get(KEY));
}
@Test
public void testGetAllNoRemove() {
Fish lance = new Fish(LANCE);
Metadata metadata = new Metadata();
metadata.put(KEY, lance);
Iterator<Fish> i = metadata.getAll(KEY).iterator();
assertSame(lance, i.next());
thrown.expect(UnsupportedOperationException.class);
i.remove();
}
@Test
public void testWriteParsed() {
Fish lance = new Fish(LANCE);

View File

@ -161,7 +161,8 @@ public class ServerServiceDefinitionTest {
.build();
assertEquals(Collections.<MethodDescriptor<?, ?>>emptyList(),
ssd.getServiceDescriptor().getMethods());
assertEquals(Collections.<ServerMethodDefinition<?, ?>>emptySet(), ssd.getMethods());
assertEquals(Collections.<ServerMethodDefinition<?, ?>>emptySet(),
new HashSet<ServerMethodDefinition<?, ?>>(ssd.getMethods()));
}
private static class NoopServerCallHandler<ReqT, RespT>