Example #1
0
    def time(self,line='', cell=None, local_ns=None):
        expr = self.shell.input_transformer_manager.transform_cell(cell)

        ## parse ast
        tp_min = 0.1
        t0 = clock()
        expr_ast = self.shell.compile.ast_parse(expr)
        tp = clock()-t0

        ## compile
        tc_min = 0.1
        t0 = clock()
        code = self.shell.compile(expr_ast, source, mode)
        tc = clock()-t0

        ## execute
        st = clock2()
        try:
            exec(code, glob, local_ns)
        except:
            self.shell.showtraceback()
            return
        end = clock2()

        # Compute actual times and report
        cpu_user = end[0]-st[0]
        cpu_sys = end[1]-st[1]
        cpu_tot = cpu_user+cpu_sys
        print("CPU times: user %s, sys: %s, total: %s" % (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)))
        if tc > tc_min:
            print("Compiler : %s" % _format_time(tc))
        if tp > tp_min:
            print("Parser   : %s" % _format_time(tp))
Example #2
0
    def logit(self, line, cell):
        """Log the execution time and file size in a sqlite database

        %%logit testid, filename [, sql_type]

        """
        user_name = self.shell.user_ns['user_name']
        extra = None
        sql_type = None

        ## Extracting the testid and filename
        inputs = line.replace(' ', '').split(',')
        if len(inputs) == 2:
            testid, filename = inputs
        elif len(inputs) == 3:
            testid, filename, extra = inputs

            if extra == 'sql_type':
                ## Get the sql_type from the shell and add it to the testid
                sql_type = self.shell.user_ns['sql_type']
                testid += '_' + sql_type
            else:
                testid += '_' + extra

        ## Current time
        ctime = time.strftime("%y-%m-%d %H:%M:%S", time.localtime())
        ns = {}
        t0 = clock()
        ## Execute the cell content
        exec(cell, self.shell.user_ns, ns)
        tc = clock() - t0

        if sql_type == 'mysql':
            filesize = -1
        else:
            if os.path.exists(self.file_name):
                filesize = os.path.getsize(filename) / 1024.**2
            else:
                filesize = -1

        ## Print the valuesi
        print testid, ':'
        print ctime
        print 'File size:', filesize, 'MB'
        print 'Creation time:', tc, 'sec'

        ## Add the values to the log database
        self.execute("INSERT INTO %s VALUES ('%s', '%s', '%s', '%s', '%s')" %
                     (self.table_name, user_name, ctime, testid, filesize, tc))

        ## Adding the result of the cell back to the shell user_ns
        for k, v in ns.iteritems():
            self.shell.user_ns[k] = v
Example #3
0
    def logit(self, line, cell):
        """Log the execution time and file size in a sqlite database

        %%logit testid, filename [, sql_type]

        """
        user_name = self.shell.user_ns['user_name']
    	extra = None
    	sql_type = None
        
        ## Extracting the testid and filename
        inputs = line.replace(' ','').split(',')
        if len(inputs) == 2:
        	testid, filename = inputs
        elif len(inputs) == 3:
        	testid, filename, extra = inputs

	        if extra == 'sql_type':
	        	## Get the sql_type from the shell and add it to the testid
	        	sql_type = self.shell.user_ns['sql_type']
	        	testid += '_' + sql_type
	        else: 
	        	testid += '_' + extra
        
        ## Current time
        ctime = time.strftime("%y-%m-%d %H:%M:%S", time.localtime())
        ns = {}
        t0 = clock()
        ## Execute the cell content
        exec(cell, self.shell.user_ns, ns)
        tc = clock() - t0
        
        if sql_type == 'mysql':
        	filesize = -1
        else:
	        if os.path.exists(self.file_name):
	            filesize = os.path.getsize(filename)/1024.**2
	        else:
	            filesize = -1

        ## Print the valuesi
        print testid,':'
        print ctime
        print 'File size:', filesize, 'MB'
        print 'Creation time:', tc, 'sec'

        ## Add the values to the log database
        self.execute("INSERT INTO %s VALUES ('%s', '%s', '%s', '%s', '%s')"%
                   (self.table_name, user_name, ctime, testid, filesize, tc))

        ## Adding the result of the cell back to the shell user_ns
        for k,v in ns.iteritems():
        	self.shell.user_ns[k] = v
Example #4
0
    def time(self,parameter_s, local_ns=None):
        """Time execution of a Python statement or expression.

        The CPU and wall clock times are printed, and the value of the
        expression (if any) is returned.  Note that under Win32, system time
        is always reported as 0, since it can not be measured.

        This function provides very basic timing functionality.  In Python
        2.3, the timeit module offers more control and sophistication, so this
        could be rewritten to use it (patches welcome).

        Examples
        --------
        ::

          In [1]: time 2**128
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00
          Out[1]: 340282366920938463463374607431768211456L

          In [2]: n = 1000000

          In [3]: time sum(range(n))
          CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
          Wall time: 1.37
          Out[3]: 499999500000L

          In [4]: time print 'hello world'
          hello world
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00

          Note that the time needed by Python to compile the given expression
          will be reported if it is more than 0.1s.  In this example, the
          actual exponentiation is done by Python at compilation time, so while
          the expression can take a noticeable amount of time to compute, that
          time is purely due to the compilation:

          In [5]: time 3**9999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s

          In [6]: time 3**999999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s
          Compiler : 0.78 s
          """

        # fail immediately if the given expression can't be compiled

        expr = self.shell.prefilter(parameter_s,False)
        
        # Minimum time above which parse time will be reported
        tp_min = 0.1
        
        t0 = clock()
        expr_ast = ast.parse(expr)
        tp = clock()-t0
        
        # Apply AST transformations
        expr_ast = self.shell.transform_ast(expr_ast)

        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
            mode = 'eval'
            source = '<timed eval>'
            expr_ast = ast.Expression(expr_ast.body[0].value)
        else:
            mode = 'exec'
            source = '<timed exec>'
        t0 = clock()
        code = compile(expr_ast, source, mode)
        tc = clock()-t0
        
        # skew measurement as little as possible
        glob = self.shell.user_ns
        wtime = time.time
        # time execution
        wall_st = wtime()
        if mode=='eval':
            st = clock2()
            out = eval(code, glob, local_ns)
            end = clock2()
        else:
            st = clock2()
            exec code in glob, local_ns
            end = clock2()
            out = None
        wall_end = wtime()
        # Compute actual times and report
        wall_time = wall_end-wall_st
        cpu_user = end[0]-st[0]
        cpu_sys = end[1]-st[1]
        cpu_tot = cpu_user+cpu_sys
        print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
              (cpu_user,cpu_sys,cpu_tot)
        print "Wall time: %.2f s" % wall_time
        if tc > tc_min:
            print "Compiler : %.2f s" % tc
        if tp > tp_min:
            print "Parser   : %.2f s" % tp
        return out
Example #5
0
    def timeit(self, line='', cell=None):
        """Time execution of a Python statement or expression

        Usage, in line mode:
          %timeit [-n<N> -r<R> [-t|-c]] statement
        or in cell mode:
          %%timeit [-n<N> -r<R> [-t|-c]] setup_code
          code
          code...

        Time execution of a Python statement or expression using the timeit
        module.  This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, the statement in the first line is used as setup code
          (executed but not timed) and the body of the cell is timed.  The cell
          body has access to any variables created in the setup code.

        Options:
        -n<N>: execute the given statement <N> times in a loop. If this value
        is not given, a fitting value is chosen.

        -r<R>: repeat the loop iteration <R> times and take the best result.
        Default: 3

        -t: use time.time to measure the time, which is the default on Unix.
        This function measures wall time.

        -c: use time.clock to measure the time, which is the default on
        Windows and measures wall time. On Unix, resource.getrusage is used
        instead and returns the CPU user time.

        -p<P>: use a precision of <P> digits to display the timing result.
        Default: 3


        Examples
        --------
        ::

          In [1]: %timeit pass
          10000000 loops, best of 3: 53.3 ns per loop

          In [2]: u = None

          In [3]: %timeit u is None
          10000000 loops, best of 3: 184 ns per loop

          In [4]: %timeit -r 4 u == None
          1000000 loops, best of 4: 242 ns per loop

          In [5]: import time

          In [6]: %timeit -n1 time.sleep(2)
          1 loops, best of 3: 2 s per loop


        The times reported by %timeit will be slightly higher than those
        reported by the timeit.py script when variables are accessed. This is
        due to the fact that %timeit executes the statement in the namespace
        of the shell, compared with timeit.py, which uses a single setup
        statement to import function or create variables. Generally, the bias
        does not matter as long as results from timeit.py are not mixed with
        those from %timeit."""

        import timeit
        import math

        # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
        # certain terminals.  Until we figure out a robust way of
        # auto-detecting if the terminal can deal with it, use plain 'us' for
        # microseconds.  I am really NOT happy about disabling the proper
        # 'micro' prefix, but crashing is worse... If anyone knows what the
        # right solution for this is, I'm all ears...
        #
        # Note: using
        #
        # s = u'\xb5'
        # s.encode(sys.getdefaultencoding())
        #
        # is not sufficient, as I've seen terminals where that fails but
        # print s
        #
        # succeeds
        #
        # See bug: https://bugs.launchpad.net/ipython/+bug/348466

        #units = [u"s", u"ms",u'\xb5',"ns"]
        units = [u"s", u"ms",u'us',"ns"]

        scaling = [1, 1e3, 1e6, 1e9]

        opts, stmt = self.parse_options(line,'n:r:tcp:',
                                        posix=False, strict=False)
        if stmt == "" and cell is None:
            return
        timefunc = timeit.default_timer
        number = int(getattr(opts, "n", 0))
        repeat = int(getattr(opts, "r", timeit.default_repeat))
        precision = int(getattr(opts, "p", 3))
        if hasattr(opts, "t"):
            timefunc = time.time
        if hasattr(opts, "c"):
            timefunc = clock

        timer = timeit.Timer(timer=timefunc)
        # this code has tight coupling to the inner workings of timeit.Timer,
        # but is there a better way to achieve that the code stmt has access
        # to the shell namespace?
        transform  = self.shell.input_splitter.transform_cell
        
        if cell is None:
            # called as line magic
            ast_setup = ast.parse("pass")
            ast_stmt = ast.parse(transform(stmt))
        else:
            ast_setup = ast.parse(transform(stmt))
            ast_stmt = ast.parse(transform(cell))
        
        ast_setup = self.shell.transform_ast(ast_setup)
        ast_stmt = self.shell.transform_ast(ast_stmt)
        
        # This codestring is taken from timeit.template - we fill it in as an
        # AST, so that we can apply our AST transformations to the user code
        # without affecting the timing code.
        timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
                                        '    setup\n'
                                        '    _t0 = _timer()\n'
                                        '    for _i in _it:\n'
                                        '        stmt\n'
                                        '    _t1 = _timer()\n'
                                        '    return _t1 - _t0\n')
        
        class TimeitTemplateFiller(ast.NodeTransformer):
            "This is quite tightly tied to the template definition above."
            def visit_FunctionDef(self, node):
                "Fill in the setup statement"
                self.generic_visit(node)
                if node.name == "inner":
                    node.body[:1] = ast_setup.body
                
                return node
            
            def visit_For(self, node):
                "Fill in the statement to be timed"
                if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
                    node.body = ast_stmt.body
                return node
        
        timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
        timeit_ast = ast.fix_missing_locations(timeit_ast)

        # Track compilation time so it can be reported if too long
        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        t0 = clock()
        code = compile(timeit_ast, "<magic-timeit>", "exec")
        tc = clock()-t0

        ns = {}
        exec code in self.shell.user_ns, ns
        timer.inner = ns["inner"]

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 10):
                if timer.timeit(number) >= 0.2:
                    break
                number *= 10

        best = min(timer.repeat(repeat, number)) / number

        if best > 0.0 and best < 1000.0:
            order = min(-int(math.floor(math.log10(best)) // 3), 3)
        elif best >= 1000.0:
            order = 0
        else:
            order = 3
        print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat,
                                                          precision,
                                                          best * scaling[order],
                                                          units[order])
        if tc > tc_min:
            print "Compiler time: %.2f s" % tc
Example #6
0
    def time(self,line='', cell=None, local_ns=None):
        """Time execution of a Python statement or expression.

        The CPU and wall clock times are printed, and the value of the
        expression (if any) is returned.  Note that under Win32, system time
        is always reported as 0, since it can not be measured.
        
        This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, you can time the cell body (a directly 
          following statement raises an error).

        This function provides very basic timing functionality.  Use the timeit 
        magic for more controll over the measurement.

        Examples
        --------
        ::

          In [1]: %time 2**128
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00
          Out[1]: 340282366920938463463374607431768211456L

          In [2]: n = 1000000

          In [3]: %time sum(range(n))
          CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
          Wall time: 1.37
          Out[3]: 499999500000L

          In [4]: %time print 'hello world'
          hello world
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00

          Note that the time needed by Python to compile the given expression
          will be reported if it is more than 0.1s.  In this example, the
          actual exponentiation is done by Python at compilation time, so while
          the expression can take a noticeable amount of time to compute, that
          time is purely due to the compilation:

          In [5]: %time 3**9999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s

          In [6]: %time 3**999999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s
          Compiler : 0.78 s
          """

        # fail immediately if the given expression can't be compiled
        
        if line and cell:
            raise UsageError("Can't use statement directly after '%%time'!")
        
        if cell:
            expr = self.shell.input_transformer_manager.transform_cell(cell)
        else:
            expr = self.shell.input_transformer_manager.transform_cell(line)

        # Minimum time above which parse time will be reported
        tp_min = 0.1

        t0 = clock()
        expr_ast = ast.parse(expr)
        tp = clock()-t0

        # Apply AST transformations
        expr_ast = self.shell.transform_ast(expr_ast)

        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        if len(expr_ast.body)==1 and isinstance(expr_ast.body[0], ast.Expr):
            mode = 'eval'
            source = '<timed eval>'
            expr_ast = ast.Expression(expr_ast.body[0].value)
        else:
            mode = 'exec'
            source = '<timed exec>'
        t0 = clock()
        code = compile(expr_ast, source, mode)
        tc = clock()-t0

        # skew measurement as little as possible
        glob = self.shell.user_ns
        wtime = time.time
        # time execution
        wall_st = wtime()
        if mode=='eval':
            st = clock2()
            out = eval(code, glob, local_ns)
            end = clock2()
        else:
            st = clock2()
            exec code in glob, local_ns
            end = clock2()
            out = None
        wall_end = wtime()
        # Compute actual times and report
        wall_time = wall_end-wall_st
        cpu_user = end[0]-st[0]
        cpu_sys = end[1]-st[1]
        cpu_tot = cpu_user+cpu_sys
        # On windows cpu_sys is always zero, so no new information to the next print 
        if sys.platform != 'win32':
            print "CPU times: user %s, sys: %s, total: %s" % \
                (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot))
        print "Wall time: %s" % _format_time(wall_time)
        if tc > tc_min:
            print "Compiler : %s" % _format_time(tc)
        if tp > tp_min:
            print "Parser   : %s" % _format_time(tp)
        return out
Example #7
0
    def timeit(self, line='', cell=None):
        """Time execution of a Python statement or expression

        Usage, in line mode:
          %timeit [-n<N> -r<R> [-t|-c]] statement
        or in cell mode:
          %%timeit [-n<N> -r<R> [-t|-c]] setup_code
          code
          code...

        Time execution of a Python statement or expression using the timeit
        module.  This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, the statement in the first line is used as setup code
          (executed but not timed) and the body of the cell is timed.  The cell
          body has access to any variables created in the setup code.

        Options:
        -n<N>: execute the given statement <N> times in a loop. If this value
        is not given, a fitting value is chosen.

        -r<R>: repeat the loop iteration <R> times and take the best result.
        Default: 3

        -t: use time.time to measure the time, which is the default on Unix.
        This function measures wall time.

        -c: use time.clock to measure the time, which is the default on
        Windows and measures wall time. On Unix, resource.getrusage is used
        instead and returns the CPU user time.

        -p<P>: use a precision of <P> digits to display the timing result.
        Default: 3


        Examples
        --------
        ::

          In [1]: %timeit pass
          10000000 loops, best of 3: 53.3 ns per loop

          In [2]: u = None

          In [3]: %timeit u is None
          10000000 loops, best of 3: 184 ns per loop

          In [4]: %timeit -r 4 u == None
          1000000 loops, best of 4: 242 ns per loop

          In [5]: import time

          In [6]: %timeit -n1 time.sleep(2)
          1 loops, best of 3: 2 s per loop


        The times reported by %timeit will be slightly higher than those
        reported by the timeit.py script when variables are accessed. This is
        due to the fact that %timeit executes the statement in the namespace
        of the shell, compared with timeit.py, which uses a single setup
        statement to import function or create variables. Generally, the bias
        does not matter as long as results from timeit.py are not mixed with
        those from %timeit."""

        import timeit

        opts, stmt = self.parse_options(line,'n:r:tcp:',
                                        posix=False, strict=False)
        if stmt == "" and cell is None:
            return
        
        timefunc = timeit.default_timer
        number = int(getattr(opts, "n", 0))
        repeat = int(getattr(opts, "r", timeit.default_repeat))
        precision = int(getattr(opts, "p", 3))
        if hasattr(opts, "t"):
            timefunc = time.time
        if hasattr(opts, "c"):
            timefunc = clock

        timer = timeit.Timer(timer=timefunc)
        # this code has tight coupling to the inner workings of timeit.Timer,
        # but is there a better way to achieve that the code stmt has access
        # to the shell namespace?
        transform  = self.shell.input_splitter.transform_cell

        if cell is None:
            # called as line magic
            ast_setup = ast.parse("pass")
            ast_stmt = ast.parse(transform(stmt))
        else:
            ast_setup = ast.parse(transform(stmt))
            ast_stmt = ast.parse(transform(cell))

        ast_setup = self.shell.transform_ast(ast_setup)
        ast_stmt = self.shell.transform_ast(ast_stmt)

        # This codestring is taken from timeit.template - we fill it in as an
        # AST, so that we can apply our AST transformations to the user code
        # without affecting the timing code.
        timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
                                        '    setup\n'
                                        '    _t0 = _timer()\n'
                                        '    for _i in _it:\n'
                                        '        stmt\n'
                                        '    _t1 = _timer()\n'
                                        '    return _t1 - _t0\n')

        class TimeitTemplateFiller(ast.NodeTransformer):
            "This is quite tightly tied to the template definition above."
            def visit_FunctionDef(self, node):
                "Fill in the setup statement"
                self.generic_visit(node)
                if node.name == "inner":
                    node.body[:1] = ast_setup.body

                return node

            def visit_For(self, node):
                "Fill in the statement to be timed"
                if getattr(getattr(node.body[0], 'value', None), 'id', None) == 'stmt':
                    node.body = ast_stmt.body
                return node

        timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
        timeit_ast = ast.fix_missing_locations(timeit_ast)

        # Track compilation time so it can be reported if too long
        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        t0 = clock()
        code = compile(timeit_ast, "<magic-timeit>", "exec")
        tc = clock()-t0

        ns = {}
        exec code in self.shell.user_ns, ns
        timer.inner = ns["inner"]

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 10):
                if timer.timeit(number) >= 0.2:
                    break
                number *= 10

        best = min(timer.repeat(repeat, number)) / number

        print u"%d loops, best of %d: %s per loop" % (number, repeat,
                                                          _format_time(best, precision))
        if tc > tc_min:
            print "Compiler time: %.2f s" % tc
Example #8
0
    def time(self, line='', cell=None, local_ns=None):
        """Time execution of a Python statement or expression.

        The CPU and wall clock times are printed, and the value of the
        expression (if any) is returned.  Note that under Win32, system time
        is always reported as 0, since it can not be measured.
        
        This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, you can time the cell body (a directly 
          following statement raises an error).

        This function provides very basic timing functionality.  Use the timeit 
        magic for more controll over the measurement.

        Examples
        --------
        ::

          In [1]: %time 2**128
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00
          Out[1]: 340282366920938463463374607431768211456L

          In [2]: n = 1000000

          In [3]: %time sum(range(n))
          CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
          Wall time: 1.37
          Out[3]: 499999500000L

          In [4]: %time print 'hello world'
          hello world
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00

          Note that the time needed by Python to compile the given expression
          will be reported if it is more than 0.1s.  In this example, the
          actual exponentiation is done by Python at compilation time, so while
          the expression can take a noticeable amount of time to compute, that
          time is purely due to the compilation:

          In [5]: %time 3**9999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s

          In [6]: %time 3**999999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s
          Compiler : 0.78 s
          """

        # fail immediately if the given expression can't be compiled

        if line and cell:
            raise UsageError("Can't use statement directly after '%%time'!")

        if cell:
            expr = self.shell.input_transformer_manager.transform_cell(cell)
        else:
            expr = self.shell.input_transformer_manager.transform_cell(line)

        # Minimum time above which parse time will be reported
        tp_min = 0.1

        t0 = clock()
        expr_ast = ast.parse(expr)
        tp = clock() - t0

        # Apply AST transformations
        expr_ast = self.shell.transform_ast(expr_ast)

        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        if len(expr_ast.body) == 1 and isinstance(expr_ast.body[0], ast.Expr):
            mode = 'eval'
            source = '<timed eval>'
            expr_ast = ast.Expression(expr_ast.body[0].value)
        else:
            mode = 'exec'
            source = '<timed exec>'
        t0 = clock()
        code = compile(expr_ast, source, mode)
        tc = clock() - t0

        # skew measurement as little as possible
        glob = self.shell.user_ns
        wtime = time.time
        # time execution
        wall_st = wtime()
        if mode == 'eval':
            st = clock2()
            out = eval(code, glob, local_ns)
            end = clock2()
        else:
            st = clock2()
            exec code in glob, local_ns
            end = clock2()
            out = None
        wall_end = wtime()
        # Compute actual times and report
        wall_time = wall_end - wall_st
        cpu_user = end[0] - st[0]
        cpu_sys = end[1] - st[1]
        cpu_tot = cpu_user + cpu_sys
        # On windows cpu_sys is always zero, so no new information to the next print
        if sys.platform != 'win32':
            print "CPU times: user %s, sys: %s, total: %s" % \
                (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot))
        print "Wall time: %s" % _format_time(wall_time)
        if tc > tc_min:
            print "Compiler : %s" % _format_time(tc)
        if tp > tp_min:
            print "Parser   : %s" % _format_time(tp)
        return out
Example #9
0
    def timeit(self, line='', cell=None):
        """Time execution of a Python statement or expression

        Usage, in line mode:
          %timeit [-n<N> -r<R> [-t|-c]] statement
        or in cell mode:
          %%timeit [-n<N> -r<R> [-t|-c]] setup_code
          code
          code...

        Time execution of a Python statement or expression using the timeit
        module.  This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, the statement in the first line is used as setup code
          (executed but not timed) and the body of the cell is timed.  The cell
          body has access to any variables created in the setup code.

        Options:
        -n<N>: execute the given statement <N> times in a loop. If this value
        is not given, a fitting value is chosen.

        -r<R>: repeat the loop iteration <R> times and take the best result.
        Default: 3

        -t: use time.time to measure the time, which is the default on Unix.
        This function measures wall time.

        -c: use time.clock to measure the time, which is the default on
        Windows and measures wall time. On Unix, resource.getrusage is used
        instead and returns the CPU user time.

        -p<P>: use a precision of <P> digits to display the timing result.
        Default: 3


        Examples
        --------
        ::

          In [1]: %timeit pass
          10000000 loops, best of 3: 53.3 ns per loop

          In [2]: u = None

          In [3]: %timeit u is None
          10000000 loops, best of 3: 184 ns per loop

          In [4]: %timeit -r 4 u == None
          1000000 loops, best of 4: 242 ns per loop

          In [5]: import time

          In [6]: %timeit -n1 time.sleep(2)
          1 loops, best of 3: 2 s per loop


        The times reported by %timeit will be slightly higher than those
        reported by the timeit.py script when variables are accessed. This is
        due to the fact that %timeit executes the statement in the namespace
        of the shell, compared with timeit.py, which uses a single setup
        statement to import function or create variables. Generally, the bias
        does not matter as long as results from timeit.py are not mixed with
        those from %timeit."""

        import timeit

        opts, stmt = self.parse_options(line,
                                        'n:r:tcp:',
                                        posix=False,
                                        strict=False)
        if stmt == "" and cell is None:
            return

        timefunc = timeit.default_timer
        number = int(getattr(opts, "n", 0))
        repeat = int(getattr(opts, "r", timeit.default_repeat))
        precision = int(getattr(opts, "p", 3))
        if hasattr(opts, "t"):
            timefunc = time.time
        if hasattr(opts, "c"):
            timefunc = clock

        timer = timeit.Timer(timer=timefunc)
        # this code has tight coupling to the inner workings of timeit.Timer,
        # but is there a better way to achieve that the code stmt has access
        # to the shell namespace?
        transform = self.shell.input_splitter.transform_cell

        if cell is None:
            # called as line magic
            ast_setup = ast.parse("pass")
            ast_stmt = ast.parse(transform(stmt))
        else:
            ast_setup = ast.parse(transform(stmt))
            ast_stmt = ast.parse(transform(cell))

        ast_setup = self.shell.transform_ast(ast_setup)
        ast_stmt = self.shell.transform_ast(ast_stmt)

        # This codestring is taken from timeit.template - we fill it in as an
        # AST, so that we can apply our AST transformations to the user code
        # without affecting the timing code.
        timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
                                        '    setup\n'
                                        '    _t0 = _timer()\n'
                                        '    for _i in _it:\n'
                                        '        stmt\n'
                                        '    _t1 = _timer()\n'
                                        '    return _t1 - _t0\n')

        class TimeitTemplateFiller(ast.NodeTransformer):
            "This is quite tightly tied to the template definition above."

            def visit_FunctionDef(self, node):
                "Fill in the setup statement"
                self.generic_visit(node)
                if node.name == "inner":
                    node.body[:1] = ast_setup.body

                return node

            def visit_For(self, node):
                "Fill in the statement to be timed"
                if getattr(getattr(node.body[0], 'value', None), 'id',
                           None) == 'stmt':
                    node.body = ast_stmt.body
                return node

        timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
        timeit_ast = ast.fix_missing_locations(timeit_ast)

        # Track compilation time so it can be reported if too long
        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        t0 = clock()
        code = compile(timeit_ast, "<magic-timeit>", "exec")
        tc = clock() - t0

        ns = {}
        exec code in self.shell.user_ns, ns
        timer.inner = ns["inner"]

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 10):
                if timer.timeit(number) >= 0.2:
                    break
                number *= 10

        best = min(timer.repeat(repeat, number)) / number

        print u"%d loops, best of %d: %s per loop" % (
            number, repeat, _format_time(best, precision))
        if tc > tc_min:
            print "Compiler time: %.2f s" % tc
Example #10
0
    def timeit2(self, line='', cell=None):

        import timeit

        opts, stmt = self.parse_options(line,
                                        'n:r:gtcp:',
                                        posix=False,
                                        strict=False)
        if stmt == "" and cell is None:
            return

        timefunc = timeit.default_timer
        number = int(getattr(opts, "n", 0))
        repeat = int(getattr(opts, "r", timeit.default_repeat))
        precision = int(getattr(opts, "p", 3))
        if hasattr(opts, "t"):
            timefunc = time.time
        if hasattr(opts, "c"):
            timefunc = clock

        if hasattr(opts, "g"):
            timer = timeit.Timer(timer=timefunc, setup='gc.enable()')
        else:
            timer = timeit.Timer(timer=timefunc)
        # this code has tight coupling to the inner workings of timeit.Timer,
        # but is there a better way to achieve that the code stmt has access
        # to the shell namespace?
        transform = self.shell.input_splitter.transform_cell

        if cell is None:
            # called as line magic
            ast_setup = ast.parse("pass")
            ast_stmt = ast.parse(transform(stmt))
        else:
            ast_setup = ast.parse(transform(stmt))
            ast_stmt = ast.parse(transform(cell))

        ast_setup = self.shell.transform_ast(ast_setup)
        ast_stmt = self.shell.transform_ast(ast_stmt)

        # This codestring is taken from timeit.template - we fill it in as an
        # AST, so that we can apply our AST transformations to the user code
        # without affecting the timing code.
        timeit_ast_template = ast.parse('def inner(_it, _timer):\n'
                                        '    setup\n'
                                        '    _t0 = _timer()\n'
                                        '    for _i in _it:\n'
                                        '        stmt\n'
                                        '    _t1 = _timer()\n'
                                        '    return _t1 - _t0\n')

        class TimeitTemplateFiller(ast.NodeTransformer):
            "This is quite tightly tied to the template definition above."

            def visit_FunctionDef(self, node):
                "Fill in the setup statement"
                self.generic_visit(node)
                if node.name == "inner":
                    node.body[:1] = ast_setup.body

                return node

            def visit_For(self, node):
                "Fill in the statement to be timed"
                if getattr(getattr(node.body[0], 'value', None), 'id',
                           None) == 'stmt':
                    node.body = ast_stmt.body
                return node

        timeit_ast = TimeitTemplateFiller().visit(timeit_ast_template)
        timeit_ast = ast.fix_missing_locations(timeit_ast)

        # Track compilation time so it can be reported if too long
        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        t0 = clock()
        code = compile(timeit_ast, "<magic-timeit>", "exec")
        tc = clock() - t0

        ns = {}
        exec code in self.shell.user_ns, ns
        timer.inner = ns["inner"]

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 10):
                if timer.timeit(number) >= 0.2:
                    break
                number *= 10

        result = timer.repeat(repeat, number)
        best = min(result) / number
        worst = max(result) / number
        avg = sum(result) / number / float(len(result))

        print u"{0} loops" \
              u"\n   AVG of {1}: {2:>5} per loop" \
              u"\n  BEST of {1}: {3:>5} per loop" \
              u"\n WORST of {1}: {4:>5} per loop".format(
                number, repeat,
                _format_time(avg, precision),
                _format_time(best, precision),
                _format_time(worst, precision)
        )
        if tc > tc_min:
            print "Compiler time: %.2f s" % tc
Example #11
0
    def time(self, parameter_s, local_ns=None):
        """Time execution of a Python statement or expression.

        The CPU and wall clock times are printed, and the value of the
        expression (if any) is returned.  Note that under Win32, system time
        is always reported as 0, since it can not be measured.

        This function provides very basic timing functionality.  In Python
        2.3, the timeit module offers more control and sophistication, so this
        could be rewritten to use it (patches welcome).

        Examples
        --------
        ::

          In [1]: time 2**128
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00
          Out[1]: 340282366920938463463374607431768211456L

          In [2]: n = 1000000

          In [3]: time sum(range(n))
          CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s
          Wall time: 1.37
          Out[3]: 499999500000L

          In [4]: time print 'hello world'
          hello world
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00

          Note that the time needed by Python to compile the given expression
          will be reported if it is more than 0.1s.  In this example, the
          actual exponentiation is done by Python at compilation time, so while
          the expression can take a noticeable amount of time to compute, that
          time is purely due to the compilation:

          In [5]: time 3**9999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s

          In [6]: time 3**999999;
          CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s
          Wall time: 0.00 s
          Compiler : 0.78 s
          """

        # fail immediately if the given expression can't be compiled

        expr = self.shell.prefilter(parameter_s, False)

        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        try:
            mode = 'eval'
            t0 = clock()
            code = compile(expr, '<timed eval>', mode)
            tc = clock() - t0
        except SyntaxError:
            mode = 'exec'
            t0 = clock()
            code = compile(expr, '<timed exec>', mode)
            tc = clock() - t0
        # skew measurement as little as possible
        glob = self.shell.user_ns
        wtime = time.time
        # time execution
        wall_st = wtime()
        if mode == 'eval':
            st = clock2()
            out = eval(code, glob, local_ns)
            end = clock2()
        else:
            st = clock2()
            exec code in glob, local_ns
            end = clock2()
            out = None
        wall_end = wtime()
        # Compute actual times and report
        wall_time = wall_end - wall_st
        cpu_user = end[0] - st[0]
        cpu_sys = end[1] - st[1]
        cpu_tot = cpu_user + cpu_sys
        print "CPU times: user %.2f s, sys: %.2f s, total: %.2f s" % \
              (cpu_user,cpu_sys,cpu_tot)
        print "Wall time: %.2f s" % wall_time
        if tc > tc_min:
            print "Compiler : %.2f s" % tc
        return out
Example #12
0
    def timeit(self, line='', cell=None):
        """Time execution of a Python statement or expression

        Usage, in line mode:
          %timeit [-n<N> -r<R> [-t|-c]] statement
        or in cell mode:
          %%timeit [-n<N> -r<R> [-t|-c]] setup_code
          code
          code...

        Time execution of a Python statement or expression using the timeit
        module.  This function can be used both as a line and cell magic:

        - In line mode you can time a single-line statement (though multiple
          ones can be chained with using semicolons).

        - In cell mode, the statement in the first line is used as setup code
          (executed but not timed) and the body of the cell is timed.  The cell
          body has access to any variables created in the setup code.

        Options:
        -n<N>: execute the given statement <N> times in a loop. If this value
        is not given, a fitting value is chosen.

        -r<R>: repeat the loop iteration <R> times and take the best result.
        Default: 3

        -t: use time.time to measure the time, which is the default on Unix.
        This function measures wall time.

        -c: use time.clock to measure the time, which is the default on
        Windows and measures wall time. On Unix, resource.getrusage is used
        instead and returns the CPU user time.

        -p<P>: use a precision of <P> digits to display the timing result.
        Default: 3


        Examples
        --------
        ::

          In [1]: %timeit pass
          10000000 loops, best of 3: 53.3 ns per loop

          In [2]: u = None

          In [3]: %timeit u is None
          10000000 loops, best of 3: 184 ns per loop

          In [4]: %timeit -r 4 u == None
          1000000 loops, best of 4: 242 ns per loop

          In [5]: import time

          In [6]: %timeit -n1 time.sleep(2)
          1 loops, best of 3: 2 s per loop


        The times reported by %timeit will be slightly higher than those
        reported by the timeit.py script when variables are accessed. This is
        due to the fact that %timeit executes the statement in the namespace
        of the shell, compared with timeit.py, which uses a single setup
        statement to import function or create variables. Generally, the bias
        does not matter as long as results from timeit.py are not mixed with
        those from %timeit."""

        import timeit
        import math

        # XXX: Unfortunately the unicode 'micro' symbol can cause problems in
        # certain terminals.  Until we figure out a robust way of
        # auto-detecting if the terminal can deal with it, use plain 'us' for
        # microseconds.  I am really NOT happy about disabling the proper
        # 'micro' prefix, but crashing is worse... If anyone knows what the
        # right solution for this is, I'm all ears...
        #
        # Note: using
        #
        # s = u'\xb5'
        # s.encode(sys.getdefaultencoding())
        #
        # is not sufficient, as I've seen terminals where that fails but
        # print s
        #
        # succeeds
        #
        # See bug: https://bugs.launchpad.net/ipython/+bug/348466

        #units = [u"s", u"ms",u'\xb5',"ns"]
        units = [u"s", u"ms", u'us', "ns"]

        scaling = [1, 1e3, 1e6, 1e9]

        opts, stmt = self.parse_options(line,
                                        'n:r:tcp:',
                                        posix=False,
                                        strict=False)
        if stmt == "" and cell is None:
            return
        timefunc = timeit.default_timer
        number = int(getattr(opts, "n", 0))
        repeat = int(getattr(opts, "r", timeit.default_repeat))
        precision = int(getattr(opts, "p", 3))
        if hasattr(opts, "t"):
            timefunc = time.time
        if hasattr(opts, "c"):
            timefunc = clock

        timer = timeit.Timer(timer=timefunc)
        # this code has tight coupling to the inner workings of timeit.Timer,
        # but is there a better way to achieve that the code stmt has access
        # to the shell namespace?
        transform = self.shell.input_splitter.transform_cell
        if cell is None:
            # called as line magic
            setup = 'pass'
            stmt = timeit.reindent(transform(stmt), 8)
        else:
            setup = timeit.reindent(transform(stmt), 4)
            stmt = timeit.reindent(transform(cell), 8)

        # From Python 3.3, this template uses new-style string formatting.
        if sys.version_info >= (3, 3):
            src = timeit.template.format(stmt=stmt, setup=setup)
        else:
            src = timeit.template % dict(stmt=stmt, setup=setup)

        # Track compilation time so it can be reported if too long
        # Minimum time above which compilation time will be reported
        tc_min = 0.1

        t0 = clock()
        code = compile(src, "<magic-timeit>", "exec")
        tc = clock() - t0

        ns = {}
        exec code in self.shell.user_ns, ns
        timer.inner = ns["inner"]

        if number == 0:
            # determine number so that 0.2 <= total time < 2.0
            number = 1
            for i in range(1, 10):
                if timer.timeit(number) >= 0.2:
                    break
                number *= 10

        best = min(timer.repeat(repeat, number)) / number

        if best > 0.0 and best < 1000.0:
            order = min(-int(math.floor(math.log10(best)) // 3), 3)
        elif best >= 1000.0:
            order = 0
        else:
            order = 3
        print u"%d loops, best of %d: %.*g %s per loop" % (
            number, repeat, precision, best * scaling[order], units[order])
        if tc > tc_min:
            print "Compiler time: %.2f s" % tc