Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(4840)

Unified Diff: chrome/common/extensions/docs/server2/in_memory_object_store.py

Issue 10829348: Extensions Docs Server: Large performance increase (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: fixes and ObjectStore Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/common/extensions/docs/server2/in_memory_object_store.py
diff --git a/chrome/common/extensions/docs/server2/in_memory_object_store.py b/chrome/common/extensions/docs/server2/in_memory_object_store.py
new file mode 100644
index 0000000000000000000000000000000000000000..f2499725a76226136caed1c4c71ff4b495e93169
--- /dev/null
+++ b/chrome/common/extensions/docs/server2/in_memory_object_store.py
@@ -0,0 +1,117 @@
+# Copyright (c) 2012 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+import time
+
+from future import Future
+from object_store import ObjectStore, CACHE_TIMEOUT
+from memcache_object_store import MemcacheObjectStore
+
+class _CacheEntry(object):
+ def __init__(self, value, expire_time):
+ self.value = value
+ self._never_expires = (expire_time == 0)
+ self._expiry = time.time() + expire_time
+
+ def HasExpired(self):
+ if self._never_expires:
+ return False
+ return time.time() > self._expiry
+
+class _AsyncGetFuture(object):
+ """A future for memcache gets.
+
+ Properties:
+ - |cache| the in-memory cache used by InMemoryObjectStore
+ - |time| the cache timeout
+ - |namespace| the namespace of the cache items
+ - |future| the |Future| from the backing |ObjectStore|
+ - |initial_mapping| a mapping of cache items already in memory
+ """
+ def __init__(self, cache, time, namespace, future, initial_mapping):
+ self._cache = cache
+ self._time = time
+ self._namespace = namespace
+ self._future = future
+ self._mapping = initial_mapping
+
+ def Get(self):
+ if self._future is not None:
+ result = self._future.Get()
+ self._cache[self._namespace].update(
+ dict((k, _CacheEntry(v, self._time)) for k, v in result.iteritems()))
+ self._mapping.update(result)
+ return self._mapping
+
+class InMemoryObjectStore(ObjectStore):
+ def __init__(self, branch):
+ self._branch = branch
+ self._cache = {}
+ self._object_store = MemcacheObjectStore()
+
+ def _SetInMemory(self, key, value, namespace, time):
+ if namespace not in self._cache:
+ self._cache[namespace] = {}
+ self._cache[namespace][key] = _CacheEntry(value, time)
+
+ def _TryBackingObjectStore(self, key, namespace, time):
+ result = self._object_store.Get(key, namespace, time=time)
+ if result is not None:
+ self._SetInMemory(key, result, namespace, time)
+ return result
+
+ def _MakeNamespace(self, namespace):
+ return 'ObjectStore.' + self._branch + '.' + namespace
not at google - send to devlin 2012/08/21 00:30:11 +'ing strings in python is inefficient, use '.'.jo
cduvall 2012/08/21 01:33:33 Done.
+
+ def Set(self, key, value, namespace, time=CACHE_TIMEOUT):
+ namespace = self._MakeNamespace(namespace)
+ self._SetInMemory(key, value, namespace, time)
+ self._object_store.Set(key, value, namespace, time=time)
+
+ def SetMulti(self, mapping, namespace, time=CACHE_TIMEOUT):
+ namespace = self._MakeNamespace(namespace)
+ for k, v in mapping.iteritems():
+ self._SetInMemory(k, v, namespace, time)
+ # TODO(cduvall): Use a batch set? App Engine kept throwing:
+ # ValueError: Values may not be more than 1000000 bytes in length
+ # for the batch set.
+ self._object_store.Set(k, v, namespace, time=time)
+
+ def Get(self, key, namespace, time=CACHE_TIMEOUT):
+ namespace = self._MakeNamespace(namespace)
+ if namespace not in self._cache:
+ return self._TryBackingObjectStore(key, namespace, time)
+ cache_entry = self._cache[namespace].get(key, None)
+ if not cache_entry:
+ return self._TryBackingObjectStore(key, namespace, time)
+ if cache_entry.HasExpired():
+ self._cache[namespace].pop(key)
+ return self._object_store.Get(key, namespace, time=time)
+ return cache_entry.value
+
+ def GetMulti(self, keys, namespace, time=CACHE_TIMEOUT):
+ namespace = self._MakeNamespace(namespace)
+ keys = keys[:]
+ mapping = {}
+ if namespace not in self._cache:
+ self._cache[namespace] = {}
+ for key in keys:
+ cache_entry = self._cache[namespace].get(key, None)
+ if cache_entry is None or cache_entry.HasExpired():
+ mapping[key] = None
+ else:
+ mapping[key] = cache_entry.value
+ keys.remove(key)
+ future = self._object_store.GetMulti(keys, namespace, time=time)
+ return Future(delegate=_AsyncGetFuture(self._cache,
+ time,
+ namespace,
+ future,
+ mapping))
+
not at google - send to devlin 2012/08/21 00:30:11 A lot of this code would be simplified by having G
cduvall 2012/08/21 01:33:33 Done.
+ def Delete(self, key, namespace):
+ namespace = self._MakeNamespace(namespace)
+ if namespace in self._cache:
+ self._cache[namespace].pop(key)
+ self._object_store.Delete(key, namespace)

Powered by Google App Engine
This is Rietveld 408576698