Author: Brian Kearns <[email protected]>
Branch:
Changeset: r61405:ab0486abc9f6
Date: 2013-02-18 09:06 -0500
http://bitbucket.org/pypy/pypy/changeset/ab0486abc9f6/
Log: significantly speed up min/max in the non-unrolled case
diff --git a/pypy/module/__builtin__/functional.py
b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -133,56 +133,76 @@
v = v.add(step)
return space.newlist(res_w)
+min_jitdriver = jit.JitDriver(name='min',
+ greens=['w_type'], reds='auto')
+max_jitdriver = jit.JitDriver(name='max',
+ greens=['w_type'], reds='auto')
+
+def make_min_max(unroll):
+ @specialize.arg(2)
+ def min_max_impl(space, args, implementation_of):
+ if implementation_of == "max":
+ compare = space.gt
+ jitdriver = max_jitdriver
+ else:
+ compare = space.lt
+ jitdriver = min_jitdriver
+ args_w = args.arguments_w
+ if len(args_w) > 1:
+ w_sequence = space.newtuple(args_w)
+ elif len(args_w):
+ w_sequence = args_w[0]
+ else:
+ msg = "%s() expects at least one argument" % (implementation_of,)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+ w_key = None
+ kwds = args.keywords
+ if kwds:
+ if kwds[0] == "key" and len(kwds) == 1:
+ w_key = args.keywords_w[0]
+ else:
+ msg = "%s() got unexpected keyword argument" %
(implementation_of,)
+ raise OperationError(space.w_TypeError, space.wrap(msg))
+
+ w_iter = space.iter(w_sequence)
+ w_type = space.type(w_iter)
+ w_max_item = None
+ w_max_val = None
+ while True:
+ if not unroll:
+ jitdriver.jit_merge_point(w_type=w_type)
+ try:
+ w_item = space.next(w_iter)
+ except OperationError, e:
+ if not e.match(space, space.w_StopIteration):
+ raise
+ break
+ if w_key is not None:
+ w_compare_with = space.call_function(w_key, w_item)
+ else:
+ w_compare_with = w_item
+ if w_max_item is None or \
+ space.is_true(compare(w_compare_with, w_max_val)):
+ w_max_item = w_item
+ w_max_val = w_compare_with
+ if w_max_item is None:
+ msg = "arg is an empty sequence"
+ raise OperationError(space.w_ValueError, space.wrap(msg))
+ return w_max_item
+ if unroll:
+ min_max_impl = jit.unroll_safe(min_max_impl)
+ return min_max_impl
+
+min_max_unroll = make_min_max(True)
+min_max_normal = make_min_max(False)
@specialize.arg(2)
[email protected]_inside_iff(lambda space, args, implementation_of:
- jit.isconstant(len(args.arguments_w)) and
- len(args.arguments_w) == 2
-)
def min_max(space, args, implementation_of):
- if implementation_of == "max":
- compare = space.gt
+ if not jit.we_are_jitted() or (jit.isconstant(len(args.arguments_w)) and
+ len(args.arguments_w) == 2):
+ return min_max_unroll(space, args, implementation_of)
else:
- compare = space.lt
- args_w = args.arguments_w
- if len(args_w) > 1:
- w_sequence = space.newtuple(args_w)
- elif len(args_w):
- w_sequence = args_w[0]
- else:
- msg = "%s() expects at least one argument" % (implementation_of,)
- raise OperationError(space.w_TypeError, space.wrap(msg))
- w_key = None
- kwds = args.keywords
- if kwds:
- if kwds[0] == "key" and len(kwds) == 1:
- w_key = args.keywords_w[0]
- else:
- msg = "%s() got unexpected keyword argument" % (implementation_of,)
- raise OperationError(space.w_TypeError, space.wrap(msg))
-
- w_iter = space.iter(w_sequence)
- w_max_item = None
- w_max_val = None
- while True:
- try:
- w_item = space.next(w_iter)
- except OperationError, e:
- if not e.match(space, space.w_StopIteration):
- raise
- break
- if w_key is not None:
- w_compare_with = space.call_function(w_key, w_item)
- else:
- w_compare_with = w_item
- if w_max_item is None or \
- space.is_true(compare(w_compare_with, w_max_val)):
- w_max_item = w_item
- w_max_val = w_compare_with
- if w_max_item is None:
- msg = "arg is an empty sequence"
- raise OperationError(space.w_ValueError, space.wrap(msg))
- return w_max_item
+ return min_max_normal(space, args, implementation_of)
def max(space, __args__):
"""max(iterable[, key=func]) -> value
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit