mirror of
				https://github.com/python/cpython.git
				synced 2025-10-31 13:41:24 +00:00 
			
		
		
		
	A nice little speed-up for filter():
- Use PyObject_Call() instead of PyEval_CallObject(), saves several layers of calls and checks. - Pre-allocate the argument tuple rather than calling Py_BuildValue() each time round the loop. - For filter(None, seq), avoid an INCREF and a DECREF.
This commit is contained in:
		
							parent
							
								
									8e829200b1
								
							
						
					
					
						commit
						c7903a13d2
					
				
					 1 changed files with 17 additions and 13 deletions
				
			
		|  | @ -122,7 +122,7 @@ Note that classes are callable, as are instances with a __call__() method."); | |||
| static PyObject * | ||||
| builtin_filter(PyObject *self, PyObject *args) | ||||
| { | ||||
| 	PyObject *func, *seq, *result, *it; | ||||
| 	PyObject *func, *seq, *result, *it, *arg; | ||||
| 	int len;   /* guess for result list size */ | ||||
| 	register int j; | ||||
| 
 | ||||
|  | @ -151,6 +151,11 @@ builtin_filter(PyObject *self, PyObject *args) | |||
| 	if (len < 0) | ||||
| 		len = 8;  /* arbitrary */ | ||||
| 
 | ||||
| 	/* Pre-allocate argument list tuple. */ | ||||
| 	arg = PyTuple_New(1); | ||||
| 	if (arg == NULL) | ||||
| 		goto Fail_arg; | ||||
| 
 | ||||
| 	/* Get a result list. */ | ||||
| 	if (PyList_Check(seq) && seq->ob_refcnt == 1) { | ||||
| 		/* Eww - can modify the list in-place. */ | ||||
|  | @ -166,7 +171,7 @@ builtin_filter(PyObject *self, PyObject *args) | |||
| 	/* Build the result list. */ | ||||
| 	j = 0; | ||||
| 	for (;;) { | ||||
| 		PyObject *item, *good; | ||||
| 		PyObject *item; | ||||
| 		int ok; | ||||
| 
 | ||||
| 		item = PyIter_Next(it); | ||||
|  | @ -177,24 +182,20 @@ builtin_filter(PyObject *self, PyObject *args) | |||
| 		} | ||||
| 
 | ||||
| 		if (func == Py_None) { | ||||
| 			good = item; | ||||
| 			Py_INCREF(good); | ||||
| 			ok = PyObject_IsTrue(item); | ||||
| 		} | ||||
| 		else { | ||||
| 			PyObject *arg = Py_BuildValue("(O)", item); | ||||
| 			if (arg == NULL) { | ||||
| 				Py_DECREF(item); | ||||
| 				goto Fail_result_it; | ||||
| 			} | ||||
| 			good = PyEval_CallObject(func, arg); | ||||
| 			Py_DECREF(arg); | ||||
| 			PyObject *good; | ||||
| 			PyTuple_SET_ITEM(arg, 0, item); | ||||
| 			good = PyObject_Call(func, arg, NULL); | ||||
| 			PyTuple_SET_ITEM(arg, 0, NULL); | ||||
| 			if (good == NULL) { | ||||
| 				Py_DECREF(item); | ||||
| 				goto Fail_result_it; | ||||
| 			} | ||||
| 		} | ||||
| 			ok = PyObject_IsTrue(good); | ||||
| 			Py_DECREF(good); | ||||
| 		} | ||||
| 		if (ok) { | ||||
| 			if (j < len) | ||||
| 				PyList_SET_ITEM(result, j, item); | ||||
|  | @ -216,12 +217,15 @@ builtin_filter(PyObject *self, PyObject *args) | |||
| 		goto Fail_result_it; | ||||
| 
 | ||||
| 	Py_DECREF(it); | ||||
| 	Py_DECREF(arg); | ||||
| 	return result; | ||||
| 
 | ||||
| Fail_result_it: | ||||
| 	Py_DECREF(result); | ||||
| Fail_it: | ||||
| 	Py_DECREF(it); | ||||
| Fail_arg: | ||||
| 	Py_DECREF(arg); | ||||
| 	return NULL; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Guido van Rossum
						Guido van Rossum