aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/utils.py
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2011-03-15 13:05:33 +1300
committerAldo Cortesi <aldo@nullcube.com>2011-03-15 13:05:33 +1300
commitfe1e2f16ff61ceaaca65f52590a5d5a4b132d790 (patch)
tree54c537fbc56cfe4ed1e1b87f927e4d0ea7adeb05 /libmproxy/utils.py
parent563d4161f120083eac79bf67cdddf28f9e9134c2 (diff)
downloadmitmproxy-fe1e2f16ff61ceaaca65f52590a5d5a4b132d790.tar.gz
mitmproxy-fe1e2f16ff61ceaaca65f52590a5d5a4b132d790.tar.bz2
mitmproxy-fe1e2f16ff61ceaaca65f52590a5d5a4b132d790.zip
Improve responsiveness of request and response viewing.
- Computing the view of a large body is expensive, so we introduce an LRU cache to hold the latest 20 results. - Use ListView more correctly, passing it individual urwid.Text snippets, rather than a single large one. This hugely improves render time.
Diffstat (limited to 'libmproxy/utils.py')
-rw-r--r--libmproxy/utils.py40
1 files changed, 39 insertions, 1 deletions
diff --git a/libmproxy/utils.py b/libmproxy/utils.py
index a64eca4e..34c49e14 100644
--- a/libmproxy/utils.py
+++ b/libmproxy/utils.py
@@ -12,7 +12,7 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
-import re, os, subprocess, datetime, textwrap, errno, sys, time
+import re, os, subprocess, datetime, textwrap, errno, sys, time, functools
def timestamp():
@@ -444,3 +444,41 @@ def dummy_cert(certdir, ca, commonname):
)
if ret: return None
return certpath
+
+
+class LRUCache:
+ """
+ A decorator that implements a self-expiring LRU cache for class
+ methods (not functions!).
+
+ Cache data is tracked as attributes on the object itself. There is
+ therefore a separate cache for each object instance.
+ """
+ def __init__(self, size=100):
+ self.size = size
+
+ def __call__(self, f):
+ cacheName = "_cached_%s"%f.__name__
+ cacheListName = "_cachelist_%s"%f.__name__
+ size = self.size
+
+ @functools.wraps(f)
+ def wrap(self, *args):
+ if not hasattr(self, cacheName):
+ setattr(self, cacheName, {})
+ setattr(self, cacheListName, [])
+ cache = getattr(self, cacheName)
+ cacheList = getattr(self, cacheListName)
+ if cache.has_key(args):
+ cacheList.remove(args)
+ cacheList.insert(0, args)
+ return cache[args]
+ else:
+ ret = f(self, *args)
+ cacheList.insert(0, args)
+ cache[args] = ret
+ if len(cacheList) > size:
+ d = cacheList.pop()
+ cache.pop(d)
+ return ret
+ return wrap