Analysis of `sqlite_synth` benchmark.

NOTE:For system specs see here

Comparison b/w py2 and py3 on sqlite_synth:

Obtained using perf module i.e. perf module([here](

  • py2 -> 6.70 us +- 0.11 us
  • py3 -> 8.49 us +- 0.16 us: 1.27x slower (+27%)

About the benchmark:

This benchmark measures the CFFI(C Foreign Function Interface) performance by going back and forth between sqlite and python.


  • Call to Lib/sqlite3 module is common to both py2 and py3.

Execpt call to ABC and use of byte-strings:

py2                                          |            py3                                            
  import collections                         |           import                              
  Binary = memoryview		                 |            Binary = buffer                             	 |           collections.Sequence.register(Row)                  

ABCs,as being discussed from start, might be the reason for slowdown(as pointed it here) and also their are bytes string used(again time is spent on that)

  • Call to Modules/_sqlite :

In connection.c

May be the code that manages the GIL:

static void _trace_callback(void* user_arg, const char* statement_string)		
	    PyObject *py_statement = NULL;		
	    PyObject *ret = NULL;		

	#ifdef WITH_THREAD		
	    PyGILState_STATE gilstate;		

	    gilstate = PyGILState_Ensure();		
	    py_statement = PyUnicode_DecodeUTF8(statement_string,		
	            strlen(statement_string), "replace");		
	    if (py_statement) {		
	        ret = PyObject_CallFunctionObjArgs((PyObject*)user_arg, py_statement, NULL);		

	    if (ret) {		
	    } else {		
	        if (_enable_callback_tracebacks) {		
	        } else {		

	#ifdef WITH_THREAD		
static PyObject* pysqlite_connection_set_trace_callback(pysqlite_Connection* self, PyObject* args, PyObject* kwargs)		
	    PyObject* trace_callback;		

	    static char *kwlist[] = { "trace_callback", NULL };		

	    if (!pysqlite_check_thread(self) || !pysqlite_check_connection(self)) {		
	        return NULL;		

	    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "O:set_trace_callback",		
	                                      kwlist, &trace_callback)) {		
	        return NULL;		

	    if (trace_callback == Py_None) {		
	        /* None clears the trace callback previously set */		
	        sqlite3_trace(self->db, 0, (void*)0);		
	    } else {		
	        if (PyDict_SetItem(self->function_pinboard, trace_callback, Py_None) == -1)		
	            return NULL;		
	        sqlite3_trace(self->db, _trace_callback, trace_callback);		


But Iā€™m not completely sure.May be I would insert time bw these regions of code to find anything useful. You can see the vmprof profiles here and opcodes here.But they are of not much help in this case.

Written on July 15, 2017