From b9cd866a0d4392820864a279f7259ae9415bd1df Mon Sep 17 00:00:00 2001 From: Kazuhiko Shiozaki <kazuhiko@nexedi.com> Date: Sun, 28 Sep 2008 20:15:51 +0000 Subject: [PATCH] * optimise sortValueList(). * use sort(key=func) instead of sort(cmp=func) if possible. * cache keyword arguments for sort(). git-svn-id: https://svn.erp5.org/repos/public/erp5/trunk@23875 20353a03-c40f-0410-a6d1-a30d3c3de9de --- product/ERP5Type/Utils.py | 120 ++++++++++++++++++++++++-------------- 1 file changed, 76 insertions(+), 44 deletions(-) diff --git a/product/ERP5Type/Utils.py b/product/ERP5Type/Utils.py index 8344fe9ff6..f3063509f4 100644 --- a/product/ERP5Type/Utils.py +++ b/product/ERP5Type/Utils.py @@ -65,62 +65,94 @@ from Accessor.TypeDefinition import list_types # Generic sort method ##################################################### +sort_kw_cache = {} + def sortValueList(value_list, sort_on=None, sort_order=None, **kw): """Sort values in a way compatible with ZSQLCatalog. """ if sort_on is not None: if isinstance(sort_on, str): sort_on = (sort_on,) - reverse = (sort_order in ('descending', 'reverse', 'DESC')) - new_sort_on = [] - for key in sort_on: - if isinstance(key, str): - new_sort_on.append((key, reverse, None)) - else: - if len(key) == 1: - new_sort_on.append((key[0], reverse, None)) - elif len(key) == 2: - new_sort_on.append((key[0], - key[1] in ('descending', 'reverse', 'DESC'), - None)) + # try to cache keyword arguments for sort() + sort_on = tuple([isinstance(x, str) and x or tuple(x) for x in sort_on]) + try: + sort_kw = sort_kw_cache[sort_on] + except KeyError: + new_sort_on = [] + reverse_dict = {} + for key in sort_on: + if isinstance(key, str): + reverse = (sort_order in ('descending', 'reverse', 'DESC')) + new_sort_on.append((key, reverse, None)) + reverse_dict[reverse] = True else: - # Emulate MySQL types - as_type = key[2].lower() - if as_type in ('int', 'bigint'): - f=int - elif as_type in ('float', 'real', 'double'): - f=float + if len(key) == 1: + reverse = (sort_order in ('descending', 'reverse', 'DESC')) + new_sort_on.append((key[0], reverse, None)) + reverse_dict[reverse] = True + elif len(key) == 2: + reverse = (key[1] in ('descending', 'reverse', 'DESC')) + new_sort_on.append((key[0], reverse, None)) + reverse_dict[reverse] = True else: - # XXX: For an unknown type, use a string. - f=str - new_sort_on.append((key[0], - key[1] in ('descending', 'reverse', 'DESC'), - f)) - sort_on = new_sort_on - - def sortValues(a, b): - result = 0 - for key, reverse, as_type in sort_on: - x = a.getProperty(key, None) - y = b.getProperty(key, None) - if as_type is not None: - try: - x = as_type(x) - y = as_type(y) - except TypeError: - pass - result = cmp(x, y) - if reverse: - result = -result - if result != 0: - break - return result + # Emulate MySQL types + as_type = key[2].lower() + if as_type in ('int', 'bigint'): + f=int + elif as_type in ('float', 'real', 'double'): + f=float + else: + # XXX: For an unknown type, use a string. + f=str + reverse = (key[1] in ('descending', 'reverse', 'DESC')) + new_sort_on.append((key[0], reverse, f)) + reverse_dict[reverse] = True + + if len(reverse_dict) == 1: + # if we have only one kind of reverse value (i.e. all True or all + # False), we can use sort(key=func) that is faster than + # sort(cmp=func). + def sortValue(a): + value_list = [] + for key, reverse, as_type in new_sort_on: + x = a.getProperty(key, None) + if as_type is not None: + try: + x = as_type(x) + except TypeError: + pass + value_list.append(x) + return value_list + sort_kw = {'key':sortValue, 'reverse':reverse} + sort_kw_cache[sort_on] = sort_kw + else: + # otherwise we use sort(cmp=func). + def sortValues(a, b): + result = 0 + for key, reverse, as_type in new_sort_on: + x = a.getProperty(key, None) + y = b.getProperty(key, None) + if as_type is not None: + try: + x = as_type(x) + y = as_type(y) + except TypeError: + pass + result = cmp(x, y) + if reverse: + result = -result + if result != 0: + break + return result + sort_kw = {'cmp':sortValues, 'reverse':reverse} + sort_kw_cache[sort_on] = sort_kw if isinstance(value_list, LazyMap): new_value_list = [x for x in value_list] value_list = new_value_list - value_list.sort(sortValues) - + + value_list.sort(**sort_kw) + return value_list ##################################################### -- 2.30.9