Подтвердить что ты не робот

Есть ли простой способ сравнения python script?

Обычно я использую команду оболочки time. Моя цель - проверить, являются ли данные маленькими, средними, большими или очень большими, сколько времени и памяти будет.

Любые инструменты для linux или просто python для этого?

4b9b3361

Ответ 1

Посмотрите timeit, профайлер python и pycallgraph.

timeit

def test():
    """Stupid test function"""
    lst = []
    for i in range(100):
        lst.append(i)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test"))

По существу, вы можете передать код python в виде строкового параметра, и он будет выполняться в указанное количество раз и печатает время выполнения. Важные биты из документов:

timeit.timeit(stmt='pass', setup='pass', timer=<default timer>, number=1000000)

Создайте экземпляр Timer с данным оператором, установите   кода и таймера и запустить его метод timeit с помощью   число исполнений.

... и:

Timer.timeit(number=1000000)

Выполнение номеров времени основного оператора. Это выполняет настройку   один раз, а затем возвращает время, необходимое для выполнения основного   несколько раз, измеряемый в секундах как поплавок.   Аргумент - это количество раз через цикл, по умолчанию - один   млн. Основной оператор, инструкция установки и функция таймера   которые будут использоваться, передаются конструктору.

     

Примечание

     
  

По умолчанию timeit временно отключает garbage collection во время синхронизации. Преимущество такого подхода состоит в том, что     он делает независимые тайминги более сопоставимыми. Этот недостаток     что ГК может быть важным компонентом     измеряемая функция. Если это так, GC можно снова включить в качестве первого     в строке настройки. Например:

         
    

timeit.Timer('for i in xrange(10): oct(i)', 'gc.enable()').timeit()

    

Профилирование

Профилирование даст вам более подробное представление о том, что происходит. Здесь "мгновенный пример" из официальных документов:

import cProfile
import re
cProfile.run('re.compile("foo|bar")')

Что вам даст:

      197 function calls (192 primitive calls) in 0.002 seconds

Ordered by: standard name

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
     1    0.000    0.000    0.001    0.001 <string>:1(<module>)
     1    0.000    0.000    0.001    0.001 re.py:212(compile)
     1    0.000    0.000    0.001    0.001 re.py:268(_compile)
     1    0.000    0.000    0.000    0.000 sre_compile.py:172(_compile_charset)
     1    0.000    0.000    0.000    0.000 sre_compile.py:201(_optimize_charset)
     4    0.000    0.000    0.000    0.000 sre_compile.py:25(_identityfunction)
   3/1    0.000    0.000    0.000    0.000 sre_compile.py:33(_compile)

Оба этих модуля должны дать вам представление о том, где искать узкие места.

Кроме того, чтобы получить доступ к выходу profile, посмотрите этот пост

pycallgraph

Этот модуль использует graphviz для создания callgraphs, таких как:

callgraph example

Вы можете легко увидеть, какие пути использовали наибольшее время по цвету. Вы можете создать их с помощью API pycallgraph или с помощью упакованного script:

pycallgraph graphviz -- ./mypythonscript.py

Накладные расходы довольно значительны. Поэтому для уже длительных процессов создание графика может занять некоторое время.

Ответ 2

Я использую простой декоратор, чтобы время func

def st_time(func):
    """
        st decorator to calculate the total time of a func
    """

    def st_func(*args, **keyArgs):
        t1 = time.time()
        r = func(*args, **keyArgs)
        t2 = time.time()
        print "Function=%s, Time=%s" % (func.__name__, t2 - t1)
        return r

    return st_func

Ответ 3

Модуль timeit был медленным и странным, поэтому я написал это:

def timereps(reps, func):
    from time import time
    start = time()
    for i in range(0, reps):
        func()
    end = time()
    return (end - start) / reps

Пример:

import os
listdir_time = timereps(10000, lambda: os.listdir('/'))
print "python can do %d os.listdir('/') per second" % (1 / listdir_time)

Для меня это говорит:

python can do 40925 os.listdir('/') per second

Это примитивный вид бенчмаркинга, но он достаточно хорош.

Ответ 4

Я обычно делаю быстрый time ./script.py, чтобы узнать, сколько времени потребуется. Это не показывает вам память, хотя, по крайней мере, не по умолчанию. Вы можете использовать /usr/bin/time -v ./script.py для получения большой информации, включая использование памяти.

Ответ 5

Посмотрите nose и на один из своих плагинов этот.

После установки нос - это script на вашем пути, и вы можете вызвать в каталоге, который содержит некоторые скрипты python:

$: nosetests

Это будет выглядеть во всех файлах python в текущем каталоге и будет выполнять любую функцию, которую он распознает как тест: например, он распознает любую функцию со словом test_ в своем имени в качестве теста.

Итак, вы можете просто создать python script, называемый test_yourfunction.py, и написать в нем что-то вроде этого:

$: cat > test_yourfunction.py

def test_smallinput():
    yourfunction(smallinput)

def test_mediuminput():
    yourfunction(mediuminput)

def test_largeinput():
    yourfunction(largeinput)

Затем вам нужно запустить

$: nosetest --with-profile --profile-stats-file yourstatsprofile.prof testyourfunction.py

и чтобы прочитать файл профиля, используйте эту строку python:

python -c "import hotshot.stats ; stats = hotshot.stats.load('yourstatsprofile.prof') ; stats.sort_stats('time', 'calls') ; stats.print_stats(200)"

Ответ 6

Профилировщик памяти для всех ваших потребностей в памяти.

https://pypi.python.org/pypi/memory_profiler

Запустите настройку pip:

pip install memory_profiler

Импортировать библиотеку:

import memory_profiler

Добавьте декоратор к элементу, который вы хотите просмотреть:

@profile
def my_func():
    a = [1] * (10 ** 6)
    b = [2] * (2 * 10 ** 7)
    del b
    return a

if __name__ == '__main__':
    my_func()

Выполнить код:

python -m memory_profiler example.py

Получить результат:

 Line #    Mem usage  Increment   Line Contents
 ==============================================
 3                           @profile
 4      5.97 MB    0.00 MB   def my_func():
 5     13.61 MB    7.64 MB       a = [1] * (10 ** 6)
 6    166.20 MB  152.59 MB       b = [2] * (2 * 10 ** 7)
 7     13.61 MB -152.59 MB       del b
 8     13.61 MB    0.00 MB       return a

Примеры из документов, связанных выше.

Ответ 7

Будьте осторожны timeit очень медленно, это займет 12 секунд на моем среднем процессор просто инициализировать (или, возможно, запустить функцию). Вы можете проверить этот принятый ответ

def test():
    lst = []
    for i in range(100):
        lst.append(i)

if __name__ == '__main__':
    import timeit
    print(timeit.timeit("test()", setup="from __main__ import test")) # 12 second

для простоты вместо этого я буду использовать time, на моем компьютере он вернет результат 0.0

import time

def test():
    lst = []
    for i in range(100):
        lst.append(i)

t1 = time.time()

test()

result = time.time() - t1
print(result) # 0.000000xxxx

Ответ 8

Самый простой способ быстро протестировать любую функцию - использовать этот синтаксис: %timeit my_code

Например:

%timeit a = 1

13.4 ns ± 0.781 ns per loop (mean ± std. dev. of 7 runs, 100000000 loops each)