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