relative speed of incremention syntaxes (or "i=i+1" VS "i+=1")

Terry Reedy tjreedy at udel.edu
Sun Aug 21 21:39:53 CEST 2011


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





More information about the Python-list mailing list