Hi,

Le Dimanche 31 Décembre 2006 01:37, Victor Stinner a écrit :
> The problem is in Canvas class. The attached patch is a proposition to fix
> the problem (double conversion). The idea is to store text encoded for the
> terminal (UTF-8) in Canvas.text but also to keep the Unicode version in
> Canvas.unitext.

Another approch is to cache calc_width() results. I attached two 
implementation:
 - dummy implementation: 7.8 sec => 2.1 sec (without any other patch)
 - LRU cache (500 entries): 7.8 => 2.3 sec (but requires Python 2.4 because of 
use of 'deque')

I don't like the idea of cache, but... it's also a solution to the performance 
problem. Problems: clear cache sometimes but also choose the good cache 
settings (cache size).

With the dummy implementation, the profiler show that :

calls  tottime  percall  cumtime  percall filename:lineno(function)
  124    0.611    0.005    1.309    0.011 curses_display.py:484(draw_screen)
 5386    0.462    0.000    1.138    0.000 canvas.py:37(__init__)
 4995    0.419    0.000    1.443    0.000 canvas.py:354(apply_text_layout)
 9748    0.319    0.000    1.055    0.000 urwid_ui.py:252(_get)
36491    0.285    0.000    0.285    0.000 util.py:877(rle_len)
  124    0.284    0.002    0.551    0.004 util.py:590(calc_text_pos)
  358    0.255    0.001    1.805    0.005 listbox.py:110(calculate_visible)

So next step: limit creation of Canvas. If we limit creation of Canvas, my 
last patches (keep widths values or cache calc_width result) may be useless.


But now I'm tired, it's near 4:00 :-)


~~~>  Happy new year ;-)  <~~~


Haypo
Seulement dans urwid-x/urwid: canvas.pyc
Seulement dans urwid-x/urwid: curses_display.pyc
Seulement dans urwid-x/urwid: escape.pyc
Seulement dans urwid-x/urwid: font.pyc
Seulement dans urwid-x/urwid: graphics.pyc
Seulement dans urwid-x/urwid: __init__.pyc
Seulement dans urwid-x/urwid: listbox.pyc
Seulement dans urwid-x/urwid: utable.pyc
diff -urb urwid-0.9.7.1/urwid/util.py urwid-x/urwid/util.py
--- urwid-0.9.7.1/urwid/util.py	2006-10-09 17:18:35.000000000 +0200
+++ urwid-x/urwid/util.py	2006-12-31 03:45:31.000000000 +0100
@@ -554,7 +554,7 @@
 	return l
 
 
-def calc_width( text, start_offs, end_offs ):
+def _calc_width( text, start_offs, end_offs ):
 	"""
 	Return the screen column width of text between start_offs and end_offs.
 	"""
@@ -579,6 +579,14 @@
 	return end_offs - start_offs
 	
 			
+def calc_width( text, start_offs, end_offs ):
+    key = hash( (text, start_offs) )
+    if key not in calc_width.cache:
+	calc_width.cache[key] = _calc_width(text, start_offs, end_offs)
+    return calc_width.cache[key]
+calc_width.cache = {}
+
+
 def calc_text_pos( text, start_offs, end_offs, pref_col ):
 	"""
 	Calculate the closest position to the screen column pref_col in text
Seulement dans urwid-x/urwid: util.pyc
Seulement dans urwid-x/urwid: widget.pyc
Seulement dans urwid-x/urwid: canvas.pyc
Seulement dans urwid-x/urwid: curses_display.pyc
Seulement dans urwid-x/urwid: escape.pyc
Seulement dans urwid-x/urwid: font.pyc
Seulement dans urwid-x/urwid: graphics.pyc
Seulement dans urwid-x/urwid: __init__.pyc
Seulement dans urwid-x/urwid: listbox.pyc
Seulement dans urwid-x/urwid: utable.pyc
diff -urb urwid-0.9.7.1/urwid/util.py urwid-x/urwid/util.py
--- urwid-0.9.7.1/urwid/util.py	2006-10-09 17:18:35.000000000 +0200
+++ urwid-x/urwid/util.py	2006-12-31 03:56:44.000000000 +0100
@@ -24,6 +24,7 @@
 
 import utable
 import escape
+from collections import deque
 
 import encodings
 
@@ -554,6 +555,61 @@
 	return l
 
 
+def lru_cache(maxsize):
+    '''Decorator applying a least-recently-used cache with the given maximum size.
+
+    Arguments to the cached function must be hashable.
+
+    Adaptation of:
+      http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/498245
+      (without cache hits/misses)
+    '''
+    def decorating_function(f):
+        cache = {}              # mapping of args to results
+        queue = deque()         # order that keys have been accessed
+        refcount = {}           # number of times each key is in the access queue
+        def wrapper(*args):
+
+            # localize variable access (ugly but fast)
+            _cache=cache; _len=len; _refcount=refcount; _maxsize=maxsize
+            queue_append=queue.append; queue_popleft = queue.popleft
+
+            # get cache entry or compute if not found
+            try:
+                result = _cache[args]
+            except KeyError:
+                result = _cache[args] = f(*args)
+
+            # record that this key was recently accessed
+            queue_append(args)
+            _refcount[args] = _refcount.get(args, 0) + 1
+
+            # Purge least recently accessed cache contents
+            while _len(_cache) > _maxsize:
+                k = queue_popleft()
+                _refcount[k] -= 1
+                if not _refcount[k]:
+                    del _cache[k]
+                    del _refcount[k]
+
+            # Periodically compact the queue by duplicate keys
+            if _len(queue) > _maxsize * 4:
+                for i in [None] * _len(queue):
+                    k = queue_popleft()
+                    if _refcount[k] == 1:
+                        queue_append(k)
+                    else:
+                        _refcount[k] -= 1
+                assert len(queue) == len(cache) == len(refcount) == sum(refcount.itervalues())
+
+            return result
+        wrapper.__doc__ = f.__doc__
+        wrapper.__name__ = f.__name__
+        return wrapper
+    return decorating_function
+
+
[EMAIL PROTECTED](maxsize=500)
 def calc_width( text, start_offs, end_offs ):
 	"""
 	Return the screen column width of text between start_offs and end_offs.
Seulement dans urwid-x/urwid: util.pyc
Seulement dans urwid-x/urwid: .util.py.swp
Seulement dans urwid-x/urwid: widget.pyc
_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid

Reply via email to