From: Simon Tatham Date: Fri, 8 Dec 2023 17:56:45 +0000 (+0000) Subject: Bodgy fix for poor performance of wcwidth. X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?a=commitdiff_plain;h=9819209e530fb943e7ba9a3d46ed25a01880de17;p=mastodonochrome.git Bodgy fix for poor performance of wcwidth. Mastodonochrome was running rather slowly, and when I profiled it, it turned out the bottleneck was the 'wcwidth' Python module, which is not a wrapper on the C function, but a reimplementation in pure Python and therefore not very fast. I've bodged it by just making one big cache of all the strings that the program ever passes to wcwidth, since there were only two calls to that function at all and they were both in text.py. I don't know if that's the right fix in the long term, but it seems to have improved things considerably for now. (Also, while I'm at it, ColouredString now wcwidths its contents once at construction time and doesn't redo it on every call, so it doesn't even look up the same thing in the cache multiple times.) --- diff --git a/text.py b/text.py index c0cd566..de68152 100644 --- a/text.py +++ b/text.py @@ -35,6 +35,12 @@ colourmap = { '-': [0, 7, 40, 36], # separator line between editor header and content } +wcswidth_cache = {} +def cached_wcswidth(s): + if s not in wcswidth_cache: + wcswidth_cache[s] = wcwidth.wcswidth(s) + return wcswidth_cache[s] + class ColouredString: def __init__(self, string, colour=' '): if isinstance(string, ColouredString): @@ -44,6 +50,7 @@ class ColouredString: assert len(colour) == 1, "Colour ids are single characters" colour = colour * len(string) self.s, self.c = string, colour + self.width = cached_wcswidth(self.s) def __add__(self, rhs): rhs = type(self)(rhs) @@ -55,10 +62,6 @@ class ColouredString: def __len__(self): return len(self.s) - @property - def width(self): - return wcwidth.wcswidth(self.s) - def __str__(self): return self.s @@ -97,7 +100,7 @@ class ColouredString: colour = self.c[pos] fraglen = len(self.c) - pos - len(self.c[pos:].lstrip(colour)) frag = self.s[pos:pos+fraglen] - yield frag, colour, wcwidth.wcswidth(frag) + yield frag, colour, cached_wcswidth(frag) pos += fraglen def split(self, width):