Fix speed regression due to PySequence_Fast in for loop.
authorRobert Bradshaw <robertwb@math.washington.edu>
Thu, 24 Jul 2008 06:02:37 +0000 (23:02 -0700)
committerRobert Bradshaw <robertwb@math.washington.edu>
Thu, 24 Jul 2008 06:02:37 +0000 (23:02 -0700)
PySequence_Fast isn't so fast after all (due to multiple branching),
was a 35% slowdown for looping over lists. Now it handles tuples as
well with only about a 4% slowdown to lists compared to before.

Cython/Compiler/ExprNodes.py

index 992d922c8266ccc77adfb72b7ed50157e5152df9..92e1e2a7e35783a2c8353f506ebf1bb3d4d9cd1d 100644 (file)
@@ -1169,20 +1169,24 @@ class NextNode(AtomicExprNode):
         self.is_temp = 1
     
     def generate_result_code(self, code):
-        code.putln(
-            "if (likely(%s != -1)) {" % self.iterator.counter.result_code)
-        code.putln(
-            "if (%s >= PySequence_Fast_GET_SIZE(%s)) break;" % (
-                self.iterator.counter.result_code,
-                self.iterator.py_result()))
-        code.putln(
-            "%s = PySequence_Fast_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
-                self.result_code,
-                self.iterator.py_result(),
-                self.iterator.counter.result_code,
-                self.result_code,
-                self.iterator.counter.result_code))
-        code.putln("} else {")
+        for py_type in ["List", "Tuple"]:
+            code.putln(
+                "if (likely(Py%s_CheckExact(%s))) {" % (py_type, self.iterator.py_result()))
+            code.putln(
+                "if (%s >= Py%s_GET_SIZE(%s)) break;" % (
+                    self.iterator.counter.result_code,
+                    py_type,
+                    self.iterator.py_result()))
+            code.putln(
+                "%s = Py%s_GET_ITEM(%s, %s); Py_INCREF(%s); %s++;" % (
+                    self.result_code,
+                    py_type,
+                    self.iterator.py_result(),
+                    self.iterator.counter.result_code,
+                    self.result_code,
+                    self.iterator.counter.result_code))
+            code.put("} else ")
+        code.putln("{")
         code.putln(
             "%s = PyIter_Next(%s);" % (
                 self.result_code,