- Ты такой душный…
- Не могли бы вы поподробнее разъяснить мне, в чём конкретно это выражается?
AMD E1-6010 6Gb Swap 0
Сегодня будем собирать пенки на кабачковой икре и протестируем несколько циклов.
Скрипт для тестирования циклов. Каждый цикл выводит два числа.
Первое - число секунд от начала цикла до вывода первого значения.
Второе - число секунд длительности цикла.
Если решите перетестировать у себя - обратите внимание, что в циклах FOR0 и GAWK число итераций прописаны константами.
В остальных - через переменную MAX. Меняйте синхронно. Выводы будут в конце. Рекомендую рассмотреть код.
Может найдете для себя что-то новое. Да, у некоторых циклов обратный порядок. Это для случаев, когда переменная цикла не используется, а важно количество итераций.
#!/bin/bash
declare -i MAX=5000000
declare -i MA1=MAX+1
declare -i Z0=0
declare -i Z1=1
declare -i P
declare LOG=./log.txt
declare LOOPNAME
clear
LOOPNAME=FOR0
P=0
SECONDS=0
for i in {1..5000000};do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=FOR1
P=0
SECONDS=0
for i in $(seq $Z1 $MAX);do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=FOR2
P=0
SECONDS=0
seq $Z1 $MAX|for i in $(</dev/stdin);do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=FOR3
P=0
SECONDS=0
for ((i=$Z0;i++<$MAX;));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=FOR4
P=0
SECONDS=0
for ((i=$MAX;i--!=0;));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=FOR5
P=0
SECONDS=0
for ((i=$Z1;i<$MA1;i++));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=WHL0
P=0
i=$Z0
SECONDS=0
while ((i++<$MAX));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
LOOPNAME=WHL1
P=0
i=$MAX
SECONDS=0
while ((i--));do
if [[ $P -eq 0 ]];then
echo $LOOPNAME $SECONDS
P=1
fi
done
echo $LOOPNAME $SECONDS
gawk 'BEGIN{p=0
for(i = 1;i < 5000000;i++){
if(p==0)
print "GAWK 0";p++}
}'
gawk 'BEGIN{t=systime();p=0
for(i = 1;i < 5000000;i++){
if(p==0){
print "GAWK " systime()-t;p++}
}
print "GAWK "systime()-t}'
FOR0 14
FOR0 76
FOR1 11
FOR1 72
FOR2 10
FOR2 53
FOR3 0
FOR3 97
FOR5 0
FOR5 103
WHL0 0
WHL0 100
WHL1 0
WHL1 78
— Я немного отделил, поскольку gawk не совсем bash, но привел для примера.
GAWK 0
GAWK 2 (тут реально 1.6) но баш оперирует целыми.
Выводы:
Самый быстрый - FOR2 for in (seq)
Самый медленный - FOR5 (сишный классический)
Несмотря на небольшие разницы в скорости выполнения скорость циклов соизмерима.
Циклы for in - ВНАЧАЛЕ получают полный список значений (в памяти) потом быстро его перебирают.
4.1 Эти циклы жрут больше памяти, в случае нехватки - может быть критическая потеря производительности при использовании swap.
4.2 У этих циклов может быть большая задержка на инициализацию цикла. Это может быть критичным - если сам цикл большой, но очень часто происходит прерывание цикла в самом начале.
awk (а gawk самый медленный awk) значительно быстрее bash. Если скорость в приоритете - используйте его.
Цикл FOR0 вообще нежелательно применять, поскольку пределы цикла и инкремент нельзя задать переменными. только константы. Но сам конструкт {1..5} применять можно и даже нужно в подстановках (но не циклах). Например: ls text{9..27}.txt.
- Главное помнить, что скорость выполнения определяется не скоростью самого цикла, а оптимизацией его тела.
Продолжение следует…








Комментарии