Я тестировал скорость Bash и Python, выполняя цикл 1 миллиард раз.
$ cat python.py
#!/bin/python
# python v3.5
i=0;
while i<=1000000000:
i=i+1;
Код Bash:
$ cat bash2.sh
#!/bin/bash
# bash v4.3
i=0
while [[ $i -le 1000000000 ]]
do
let i++
done
Используя time
команду, я обнаружил, что завершение кода Python занимает всего 48 секунд, в то время как код Bash занял более 1 часа, прежде чем я убил скрипт.
Почему это так? Я ожидал, что Баш будет быстрее. Что-то не так с моим скриптом или Bash действительно намного медленнее с этим скриптом?
echo echo hello >> $0
и запустите его.Ответы:
Это известная ошибка в bash; см. справочную страницу и выполните поиск по запросу «ОШИБКИ»:
;)
Для отличного понимания концептуальных различий между сценариями оболочки и другими языками программирования я настоятельно рекомендую прочитать:
Самые подходящие выдержки:
Не используйте большие циклы в сценариях оболочки.
источник
Циклы оболочки медленные, а bash самые медленные. Снаряды не предназначены для тяжелой работы в петлях. Оболочки предназначены для запуска нескольких внешних оптимизированных процессов в пакетах данных.
В любом случае, мне было любопытно, как сравниваются циклы оболочки, поэтому я сделал небольшой тест:
( Подробности:
)
(Сокращенные) результаты (время на итерацию):
Из результатов:
Если вам нужен немного более быстрый цикл оболочки, то если у вас есть
[[
синтаксис и вы хотите быстрый цикл оболочки, вы находитесь в расширенной оболочке и у вас также есть цикл C-like for. Тогда используйте C как для цикла. Они могут быть примерно в 2 раза быстрее, чемwhile [
-loops в одной и той же оболочке.for (
цикл - около 2,7 мкс за итерациюwhile [
цикл - около 5,8 мкс за итерациюC для циклов может быть на 3-4 десятичных порядка быстрее. (Я слышал, что Торвальдс любит C).
Оптимизированный цикл C for в 56500 раз быстрее, чем
while [
цикл bash (самый медленный цикл оболочки), и в 6750 раз быстрее, чемfor (
цикл ksh (самый быстрый цикл оболочки).Опять же, медлительность оболочек не должна иметь большого значения, потому что типичная схема с оболочками - это разгрузка нескольких процессов внешних оптимизированных программ.
С этим шаблоном оболочки часто упрощают написание сценариев с производительностью, превосходящей сценарии Python (в прошлый раз, когда я проверял, создание конвейеров процессов в python было довольно неуклюжим).
Еще одна вещь, чтобы рассмотреть это время запуска.
занимает от 30 до 40 мс на моем ПК, тогда как оболочка занимает около 3 мс Если вы запускаете много скриптов, это быстро складывается, и вы можете очень много сделать за дополнительные 27-37 мс, которые питон берет, чтобы начать. Небольшие сценарии могут быть завершены несколько раз за этот период времени.
(NodeJs, вероятно, является худшей средой выполнения сценариев в этом отделе, поскольку для ее запуска требуется около 100 мс (хотя после ее запуска вам будет сложно найти лучшего исполнителя среди языков сценариев)).
источник
ksh88
, AT & Tksh93
,pdksh
,mksh
...) , поскольку есть довольно много вариаций между ними. Дляbash
, вы можете указать версию. В последнее время достигнут определенный прогресс (это относится и к другим оболочкам).from subprocess import *; p1=Popen(['echo', 'something'], stdout=PIPE); p2 = Popen(['grep', 'pattern'], stdin=p1.stdout, stdout=PIPE); Popen(['wc', '-c'], stdin=PIPE)
. Это действительно неуклюже, но не должно быть сложно написатьpipeline
функцию, которая сделает это за вас для любого числа процессов, что приведет кpipeline(['echo', 'something'], ['grep', 'patter'], ['wc', '-c'])
.Я провел небольшое тестирование, и в моей системе запустилось следующее - ни один из них не увеличил на порядок, что было бы необходимо для конкурентоспособности, но вы можете сделать это быстрее:
Тест 1: 18.233 с
тест2: 20,45 с
test3: 17.64 с
test4: 26,69 с
тест5: 12,79 с
Важной частью этого последнего является экспорт LC_ALL = C. Я обнаружил, что многие операции bash заканчиваются значительно быстрее, если это используется, в частности, любая функция регулярного выражения. Он также показывает недокументированный синтаксис для использования {} и: в качестве запрета.
источник
[[
это намного быстрее, чем[
. Я не знал, что LC_ALL = C (кстати, вам не нужно его экспортировать) имеет значение.[[
это встроенный bash, и[
он действительно/bin/[
такой же, как/bin/test
и внешняя программа. Вот почему это медленнее.[
является встроенным во все общие оболочки (попробуйтеtype [
). Внешняя программа сейчас в основном не используется.Оболочка эффективна, если вы используете ее для того, для чего она была разработана (хотя эффективность редко бывает тем, что вы ищете в оболочке).
Оболочка является интерпретатором командной строки, она предназначена для запуска команд и обеспечения их взаимодействия с задачей.
Если вы хотите , чтобы рассчитывать на 1000000000, вы вызываете команду (один) , чтобы рассчитывать, как
seq
,bc
,awk
илиpython
/perl
... Запуск 1000000000[[...]]
команды и 1000000000let
команды обязано быть очень неэффективными, особенно сbash
это самой медленной оболочкой всех.В этом отношении оболочка будет намного быстрее:
Хотя, конечно, большая часть работы выполняется командами, которые вызывает оболочка, как и должно быть.
Теперь вы можете сделать то же самое с
python
:Но это не совсем , как вы могли бы сделать вещи ,
python
какpython
это прежде всего язык программирования, а не интерпретатор командной строки.Обратите внимание, что вы можете сделать:
Но на
python
самом деле будет вызывать оболочку для интерпретации этой командной строки!источник
Ответ: Bash намного медленнее, чем Python.
Один небольшой пример - в блоге. Представление на нескольких языках .
источник
Нет ничего плохого (кроме ваших ожиданий), так как python действительно довольно быстр для некомпилированного языка, см. Https://wiki.python.org/moin/PythonSpeed
источник
Помимо комментариев, вы можете немного оптимизировать код , например,
Этот код должен занять немного меньше времени.
Но, очевидно, недостаточно быстро, чтобы его можно было использовать на самом деле.
источник
Я заметил существенное отличие bash от использования логически эквивалентных выражений while и while:
Не то, чтобы это действительно имело огромное значение для вопроса, кроме того, что иногда, возможно, небольшие различия имеют большое значение, даже если мы ожидаем, что они будут эквивалентны.
источник
((i==900000))
.=
для назначения. Это вернет истину немедленно. Никакой петли не будет.