On 8/21/2011 1:27 PM, Andreas Löscher wrote:
What the precise difference (semantics and speed) is between the
BINARY_ADD and INPLACE_ADD opcodes, I dunno. Look in the Python source
code or maybe someone knows it from memory :-)

Irmen

from Python/ceval.c:

1316            case BINARY_ADD:
1317                w = POP();
1318                v = TOP();
1319                if (PyInt_CheckExact(v)&&  PyInt_CheckExact(w)) {
1320                    /* INLINE: int + int */
1321                    register long a, b, i;
1322                    a = PyInt_AS_LONG(v);
1323                    b = PyInt_AS_LONG(w);
1324                    /* cast to avoid undefined behaviour
1325                       on overflow */
1326                    i = (long)((unsigned long)a + b);
1327                    if ((i^a)<  0&&  (i^b)<  0)
1328                        goto slow_add;
1329                    x = PyInt_FromLong(i);
1330                }
1331                else if (PyString_CheckExact(v)&&
1332                         PyString_CheckExact(w)) {
1333                    x = string_concatenate(v, w, f, next_instr);
1334                    /* string_concatenate consumed the ref to v */
1335                    goto skip_decref_vx;
1336                }
1337                else {
1338                  slow_add:
1339                    x = PyNumber_Add(v, w);
1340                }
1341                Py_DECREF(v);
1342              skip_decref_vx:
1343                Py_DECREF(w);
1344                SET_TOP(x);
1345                if (x != NULL) continue;
1346                break;

1532            case INPLACE_ADD:
1533                w = POP();
1534                v = TOP();
1535                if (PyInt_CheckExact(v)&&  PyInt_CheckExact(w)) {
1536                    /* INLINE: int + int */
1537                    register long a, b, i;
1538                    a = PyInt_AS_LONG(v);
1539                    b = PyInt_AS_LONG(w);
1540                    i = a + b;
1541                    if ((i^a)<  0&&  (i^b)<  0)
1542                        goto slow_iadd;
1543                    x = PyInt_FromLong(i);
1544                }
1545                else if (PyString_CheckExact(v)&&
1546                         PyString_CheckExact(w)) {
1547                    x = string_concatenate(v, w, f, next_instr);
1548                    /* string_concatenate consumed the ref to v */
1549                    goto skip_decref_v;
1550                }
1551                else {
1552                  slow_iadd:
1553                    x = PyNumber_InPlaceAdd(v, w);
1554                }
1555                Py_DECREF(v);
1556              skip_decref_v:
1557                Py_DECREF(w);
1558                SET_TOP(x);
1559                if (x != NULL) continue;
1560                break;

As for using Integers, the first case (line 1319 and 1535) are true and
there is no difference in Code. However, Python uses a huge switch-case
construct to execute it's opcodes and INPLACE_ADD cames after
BINARY_ADD, hence the difference in speed.

To be clear, this is nothing you should consider when writing fast code.
Complexity wise they both are the same.

With 64 bit 3.2.2 on my Win 7 Pentium, the difference was 4% and with floats (0.0 and 1.0), 6%

--
Terry Jan Reedy


--
http://mail.python.org/mailman/listinfo/python-list

Reply via email to