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 ConstructorConstructor constructorConstructor;
|
||||
|
||||
|
@ -328,7 +331,10 @@ public final class Gson {
|
|||
* deserialize {@code 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();
|
||||
@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);
|
||||
if (candidate != null) {
|
||||
call.setDelegate(candidate);
|
||||
typeTokenCache.put(type, 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