Construct BuiltinSumWithGenerator

Performance Diagrams

Construct BuiltinSumWithGenerator 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000CPython 2.7Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)19085305072.9230769230769296.6373653873429CPython 2.70194.46153846153845504.11538461538464Nuitka (historic)221355816316.0263.4775417918779Nuitka (master)227314320437.53846153846143257.0Nuitka (develop)227314314559.0769230769231257.0000065226525Nuitka (factory)Construct BuiltinSumWithGeneratorTicks Construct BuiltinSumWithGenerator 002000000020000000400000004000000060000000600000008000000080000000100000000100000000120000000120000000140000000140000000160000000160000000180000000180000000200000000200000000220000000220000000240000000240000000260000000260000000280000000280000000300000000300000000CPython 3.5Nuitka (historic)Nuitka (master)Nuitka (develop)Nuitka (factory)30373519072.9230769230769257.0CPython 3.50194.46153846153845504.11538461538464Nuitka (historic)266238908316.0287.50653481434574Nuitka (master)273211099437.53846153846143281.83404207296496Nuitka (develop)273209737559.0769230769231281.83515018017454Nuitka (factory)Construct BuiltinSumWithGeneratorTicks

Source Code with Construct

empty = ()

def calledRepeatedly():
    # We measure making a generator iterator step or not.
    gen = (x for x in range(1000))

    # This should abort.
# construct_begin
    y = sum(gen)
# construct_alternative



    return y, gen

for x in xrange(500):
    calledRepeatedly()

print("OK.")

Source Code without Construct

empty = ()

def calledRepeatedly():
    # We measure making a generator iterator step or not.
    gen = (x for x in range(1000))

    # This should abort.
# construct_begin

# construct_alternative
    y = gen
# construct_end

    return y, gen

for x in xrange(500):
    calledRepeatedly()

print("OK.")

Context Diff of Source Code


Construct
Baseline
24     # We measure making a generator iterator step or not. 24     # We measure making a generator iterator step or not.
25     gen = (x for x in range(1000)) 25     gen = (x for x in range(1000))
26 26
27     # This should abort. 27     # This should abort.
28 # construct_begin 28 # construct_begin
n 29     y = sum(gen) n 29  
30 # construct_alternative 30 # construct_alternative
t 31   t 31     y = gen
32   32 # construct_end
33 33
34     return y, gen 34     return y, gen
35 35
36 for x in xrange(500): 36 for x in xrange(500):
37     calledRepeatedly() 37     calledRepeatedly()

Context Diff of Generated Code


Construct
Baseline
138 #endif 138 #endif
139 139
140     // Local variable declarations. 140     // Local variable declarations.
141     PyObject *var_gen = NULL; 141     PyObject *var_gen = NULL;
142     PyObject *var_y = NULL; 142     PyObject *var_y = NULL;
n 143     PyObject *exception_type = NULL, *exception_value = NULL; n
144     PyTracebackObject *exception_tb = NULL;
145     NUITKA_MAY_BE_UNUSED int exception_lineno = -1;
146     PyObject *exception_keeper_type_1;
147     PyObject *exception_keeper_value_1;
148     PyTracebackObject *exception_keeper_tb_1;
149     NUITKA_MAY_BE_UNUSED int exception_keeper_lineno_1;
150     PyObject *tmp_assign_source_1; 143     PyObject *tmp_assign_source_1;
151     PyObject *tmp_assign_source_2; 144     PyObject *tmp_assign_source_2;
152     PyObject *tmp_dircall_arg1_1; 145     PyObject *tmp_dircall_arg1_1;
n 153     PyObject *tmp_frame_locals; n
154     PyObject *tmp_iter_arg_1; 146     PyObject *tmp_iter_arg_1;
155     PyObject *tmp_return_value; 147     PyObject *tmp_return_value;
n 156     PyObject *tmp_sum_sequence_1; n
157     PyObject *tmp_tuple_element_1; 148     PyObject *tmp_tuple_element_1;
n 158     static PyFrameObject *cache_frame_function = NULL; n
159  
160     PyFrameObject *frame_function;
161  
162     tmp_return_value = NULL; 149     tmp_return_value = NULL;
163 150
164     // Actual function code. 151     // Actual function code.
165     tmp_iter_arg_1 = const_xrange_0_1000; 152     tmp_iter_arg_1 = const_xrange_0_1000;
166     tmp_dircall_arg1_1 = MAKE_ITERATOR( tmp_iter_arg_1 ); 153     tmp_dircall_arg1_1 = MAKE_ITERATOR( tmp_iter_arg_1 );
172     } 159     }
173     assert( tmp_assign_source_1 != NULL ); 160     assert( tmp_assign_source_1 != NULL );
174     assert( var_gen == NULL ); 161     assert( var_gen == NULL );
175     var_gen = tmp_assign_source_1; 162     var_gen = tmp_assign_source_1;
176 163
n n 164     tmp_assign_source_2 = var_gen;
165  
166     assert( var_y == NULL );
167     Py_INCREF( tmp_assign_source_2 );
168     var_y = tmp_assign_source_2;
169  
177     // Tried code: 170     // Tried code:
n 178     MAKE_OR_REUSE_FRAME( cache_frame_function, codeobj_53bf6f86eec908c25f869f31af799c95, module___main__ ); n
179     frame_function = cache_frame_function;
180  
181     // Push the new frame as the currently active one.
182     pushFrameStack( frame_function );
183  
184     // Mark the frame object as in use, ref count 1 will be up for reuse.
185     Py_INCREF( frame_function );
186     assert( Py_REFCNT( frame_function ) == 2 ); // Frame stack
187  
188 #if PYTHON_VERSION >= 340
189     frame_function->f_executing += 1;
190 #endif
191  
192     // Framed code:
193     tmp_sum_sequence_1 = var_gen;
194  
195     tmp_assign_source_2 = BUILTIN_SUM1( tmp_sum_sequence_1 );
196     if ( tmp_assign_source_2 == NULL )
197     {
198         assert( ERROR_OCCURRED() );
199  
200         FETCH_ERROR_OCCURRED( &exception_type, &exception_value, &exception_tb );
201  
202  
203         exception_lineno = 29;
204         goto frame_exception_exit_1;
205     }
206     assert( var_y == NULL );
207     var_y = tmp_assign_source_2;
208  
209  
210 #if 0
211     RESTORE_FRAME_EXCEPTION( frame_function );
212 #endif
213     // Put the previous frame back on top.
214     popFrameStack();
215 #if PYTHON_VERSION >= 340
216     frame_function->f_executing -= 1;
217 #endif
218     Py_DECREF( frame_function );
219     goto frame_no_exception_1;
220  
221     frame_exception_exit_1:;
222 #if 0
223     RESTORE_FRAME_EXCEPTION( frame_function );
224 #endif
225  
226     {
227         bool needs_detach = false;
228  
229         if ( exception_tb == NULL )
230         {
231             exception_tb = MAKE_TRACEBACK( frame_function, exception_lineno );
232             needs_detach = true;
233         }
234         else if ( exception_lineno != -1 )
235         {
236             PyTracebackObject *traceback_new = MAKE_TRACEBACK( frame_function, exception_lineno );
237             traceback_new->tb_next = exception_tb;
238             exception_tb = traceback_new;
239  
240             needs_detach = true;
241         }
242  
243         if (needs_detach)
244         {
245  
246             tmp_frame_locals = PyDict_New();
247             if ( var_gen )
248             {
249                 int res = PyDict_SetItem(
250                     tmp_frame_locals,
251                     const_str_plain_gen,
252                     var_gen
253                 );
254  
255                 assert( res == 0 );
256             }
257  
258             if ( var_y )
259             {
260                 int res = PyDict_SetItem(
261                     tmp_frame_locals,
262                     const_str_plain_y,
263                     var_y
264                 );
265  
266                 assert( res == 0 );
267             }
268  
269  
270  
271             detachFrame( exception_tb, tmp_frame_locals );
272         }
273     }
274  
275     popFrameStack();
276  
277 #if PYTHON_VERSION >= 340
278     frame_function->f_executing -= 1;
279 #endif
280     Py_DECREF( frame_function );
281  
282     // Return the error.
283     goto try_except_handler_1;
284  
285     frame_no_exception_1:;
286  
287     tmp_return_value = PyTuple_New( 2 ); 171     tmp_return_value = PyTuple_New( 2 );
288     tmp_tuple_element_1 = var_y; 172     tmp_tuple_element_1 = var_y;
289 173
290     Py_INCREF( tmp_tuple_element_1 ); 174     Py_INCREF( tmp_tuple_element_1 );
291     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 ); 175     PyTuple_SET_ITEM( tmp_return_value, 0, tmp_tuple_element_1 );
305 189
306     Py_XDECREF( var_y ); 190     Py_XDECREF( var_y );
307     var_y = NULL; 191     var_y = NULL;
308 192
309     goto function_return_exit; 193     goto function_return_exit;
n 310     // Exception handler code: n
311     try_except_handler_1:;
312     exception_keeper_type_1 = exception_type;
313     exception_keeper_value_1 = exception_value;
314     exception_keeper_tb_1 = exception_tb;
315     exception_keeper_lineno_1 = exception_lineno;
316     exception_type = NULL;
317     exception_value = NULL;
318     exception_tb = NULL;
319     exception_lineno = -1;
320  
321     CHECK_OBJECT( (PyObject *)var_gen );
322     Py_DECREF( var_gen );
323     var_gen = NULL;
324  
325     // Re-raise.
326     exception_type = exception_keeper_type_1;
327     exception_value = exception_keeper_value_1;
328     exception_tb = exception_keeper_tb_1;
329     exception_lineno = exception_keeper_lineno_1;
330  
331     goto function_exception_exit;
332     // End of try: 194     // End of try:
333 195
334     // Return statement must have exited already. 196     // Return statement must have exited already.
335     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly ); 197     NUITKA_CANNOT_GET_HERE( __main__$$$function_1_calledRepeatedly );
336     return NULL; 198     return NULL;
337 199
t 338 function_exception_exit: t
339     assert( exception_type );
340     RESTORE_ERROR_OCCURRED( exception_type, exception_value, exception_tb );
341  
342     return NULL;
343     function_return_exit: 200     function_return_exit:
344 201
345     CHECK_OBJECT( tmp_return_value ); 202     CHECK_OBJECT( tmp_return_value );
346     assert( had_error || !ERROR_OCCURRED() ); 203     assert( had_error || !ERROR_OCCURRED() );
347     return tmp_return_value; 204     return tmp_return_value;