Cache all computed type adapters. On one particularly violent test (issue 375) this improves performance by 77%.
This commit is contained in:
parent
ddde79c861
commit
4c06b01369
|
@ -114,6 +114,9 @@ public final class Gson {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private final Map<TypeToken<?>, TypeAdapter<?>> typeTokenCache
|
||||||
|
= Collections.synchronizedMap(new HashMap<TypeToken<?>, TypeAdapter<?>>());
|
||||||
|
|
||||||
private final List<TypeAdapter.Factory> factories;
|
private final List<TypeAdapter.Factory> factories;
|
||||||
private final ConstructorConstructor constructorConstructor;
|
private final ConstructorConstructor constructorConstructor;
|
||||||
|
|
||||||
|
@ -328,7 +331,10 @@ public final class Gson {
|
||||||
* deserialize {@code type}.
|
* deserialize {@code type}.
|
||||||
*/
|
*/
|
||||||
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
|
public <T> TypeAdapter<T> getAdapter(TypeToken<T> type) {
|
||||||
// TODO: cache?
|
TypeAdapter<?> cached = typeTokenCache.get(type);
|
||||||
|
if (cached != null) {
|
||||||
|
return (TypeAdapter<T>) cached;
|
||||||
|
}
|
||||||
|
|
||||||
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
|
Map<TypeToken<?>, FutureTypeAdapter<?>> threadCalls = calls.get();
|
||||||
@SuppressWarnings("unchecked") // the key and value type parameters always agree
|
@SuppressWarnings("unchecked") // the key and value type parameters always agree
|
||||||
|
@ -344,6 +350,7 @@ public final class Gson {
|
||||||
TypeAdapter<T> candidate = factory.create(this, type);
|
TypeAdapter<T> candidate = factory.create(this, type);
|
||||||
if (candidate != null) {
|
if (candidate != null) {
|
||||||
call.setDelegate(candidate);
|
call.setDelegate(candidate);
|
||||||
|
typeTokenCache.put(type, candidate);
|
||||||
return candidate;
|
return candidate;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* 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 com.google.gson;
|
|
||||||
|
|
||||||
|
|
||||||
import java.util.LinkedHashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A cache that evict objects from the cache using an LRU (least recently used)
|
|
||||||
* policy. Object start getting evicted from the cache once the {@code maxCapacity}
|
|
||||||
* is reached.
|
|
||||||
*
|
|
||||||
* @author Inderjeet Singh
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
final class LruCache<K, V> extends LinkedHashMap<K, V> {
|
|
||||||
private final int maxCapacity;
|
|
||||||
|
|
||||||
public LruCache(int maxCapacity) {
|
|
||||||
super(maxCapacity, 0.7F, true);
|
|
||||||
this.maxCapacity = maxCapacity;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override protected boolean removeEldestEntry(Map.Entry<K, V> entry) {
|
|
||||||
return size() > maxCapacity;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,83 +0,0 @@
|
||||||
/*
|
|
||||||
* Copyright (C) 2010 Google Inc.
|
|
||||||
*
|
|
||||||
* 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 com.google.gson;
|
|
||||||
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unit test for the {@link LruCache} class.
|
|
||||||
*
|
|
||||||
* @author Inderjeet Singh
|
|
||||||
* @author Joel Leitch
|
|
||||||
*/
|
|
||||||
public class LruCacheTest extends TestCase {
|
|
||||||
|
|
||||||
public void testCacheHitAndMiss() throws Exception {
|
|
||||||
LruCache<String, Integer> cache = new LruCache<String, Integer>(3);
|
|
||||||
|
|
||||||
String key = "key1";
|
|
||||||
assertNull(cache.get(key));
|
|
||||||
cache.put(key, 1);
|
|
||||||
assertEquals(1, cache.get(key).intValue());
|
|
||||||
|
|
||||||
String key2 = "key2";
|
|
||||||
cache.put(key2, 2);
|
|
||||||
assertEquals(1, cache.get(key).intValue());
|
|
||||||
assertEquals(2, cache.get(key2).intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCacheKeyOverwrite() throws Exception {
|
|
||||||
LruCache<String, Integer> cache = new LruCache<String, Integer>(3);
|
|
||||||
|
|
||||||
String key = "key1";
|
|
||||||
assertNull(cache.get(key));
|
|
||||||
cache.put(key, 1);
|
|
||||||
assertEquals(1, cache.get(key).intValue());
|
|
||||||
|
|
||||||
cache.put(key, 5);
|
|
||||||
assertEquals(5, cache.get(key).intValue());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void testCacheEviction() throws Exception {
|
|
||||||
LruCache<String, Integer> cache = new LruCache<String, Integer>(5);
|
|
||||||
|
|
||||||
cache.put("key1", 1);
|
|
||||||
cache.put("key2", 2);
|
|
||||||
cache.put("key3", 3);
|
|
||||||
cache.put("key4", 4);
|
|
||||||
cache.put("key5", 5);
|
|
||||||
assertEquals(1, cache.get("key1").intValue());
|
|
||||||
assertEquals(2, cache.get("key2").intValue());
|
|
||||||
assertEquals(3, cache.get("key3").intValue());
|
|
||||||
assertEquals(4, cache.get("key4").intValue());
|
|
||||||
assertEquals(5, cache.get("key5").intValue());
|
|
||||||
|
|
||||||
// Access key1 to show key2 will be evicted (shows not a FIFO cache)
|
|
||||||
cache.get("key1");
|
|
||||||
cache.get("key3");
|
|
||||||
cache.put("key6", 6);
|
|
||||||
cache.put("key7", 7);
|
|
||||||
assertEquals(1, cache.get("key1").intValue());
|
|
||||||
assertNull(cache.get("key2"));
|
|
||||||
assertEquals(3, cache.get("key3").intValue());
|
|
||||||
assertNull(cache.get("key4"));
|
|
||||||
assertEquals(5, cache.get("key5").intValue());
|
|
||||||
assertEquals(6, cache.get("key6").intValue());
|
|
||||||
assertEquals(7, cache.get("key7").intValue());
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user