LINUX.ORG.RU

Как узнать время работы команды cd?

 ,


1

1

Играюсь здесь с ЯДом... Решил сделать протокол. Делаю:

# /usr/bin/time "cd /e"
/usr/bin/time: cannot run cd /e: No such file or directory
Command exited with non-zero status 127
0.00user 0.00system 0:00.00elapsed 61%CPU (0avgtext+0avgdata 1240maxresident)k
0inputs+0outputs (0major+37minor)pagefaults 0swaps

Это встроенная команда шелла, со всеми вытекающими.
И? Как запротоколировать время работы команды cd?

★★★

Во-первых, у тебя ошибка — кавычки не нужны. Команды "cd /e" (как единого файла) нет (и даже быть не может из-за слеша — он недопустим в именах файлов).

Во-вторых, время на cd будет 0.000, очевидно. Если прям очеь-очень хочется замерить непонятно что, сделай небольшой скрипт, первой строкой запоминаешь текущее время, потом миллиард (а лучше триллион) раз cd туда-сюда, в конце из текущего времени вычитаешь то, что запомнил в начале. Ну и делишь на свой миллиард, чтобы получить среднее.

Не очень, правда, понятно, зачем это вообще хоть кому-то может быть надо…


upd:

Там сам пустой цикл дофига занимает, поэтому придётся так:

#!/bin/bash
iterations=10000000

counter=$iterations
starttime=$(date +%s)
while [ $counter -ge 0 ]
do
    ((counter--))
done
endtime=$(date +%s)
echo Empty loop is $((endtime-starttime)) seconds


counter=$iterations
starttime=$(date +%s)
while [ $counter -ge 0 ]
do
    cd /usr/bin
    ((counter--))
    cd /usr/lib
done
endtime=$(date +%s)
echo cd loop is $((endtime-starttime)) seconds

Вывод:

Empty loop is 24 seconds
cd loop is 114 seconds

Соответственно разница — 90 секунд. Делим пополам (поскольку в каждой итерации два раза вызывается cd, а не один) — 45 секунд на 10 млн cd. Соответственно время выполнения одного cd — примерно 4.5 микросекунды. Примерно. Порядок такой; конечно, на деле может быть и 3 и 5 микросекунд. Но не полсекунды и не наносекунду.

Можешь у себя замерить таким же образом.

И если не секрет, нафига оно тебе?

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 7)
Ответ на: комментарий от anonymous

Если это точка монтирования с автомонтированием (сетевой шары!)?

Что это за автомонтирование такое, которое на cd реагирует?

А если это сетевой диск?

Какая разница, команде cd не интересно содержимое каталога

annulen ★★★★★
()
Ответ на: комментарий от annulen

Что это за автомонтирование такое, которое на cd реагирует?

В systemd есть такое. На 100% не уверен, правда, реагирует ли оно на cd, или нужен обязательно ls.

CrX ★★★★★
()

Ещё вариант, если нужна точность, вкорячить секундомер в сам шелл - опенсорс же. Скажем, для bash можно обернуть вызов cd_builtin в пару gettimeofday вот здесь. Могу ошибаться, сырцы баша вижу впервые.

У gettimeofday точность вроде как наносекундная, верится, правда, с трудом ) И да, сами вызовы времени тоже добавят.

JaneDoe
()
Последнее исправление: JaneDoe (всего исправлений: 1)
Ответ на: комментарий от anonymous

Если это точка монтирования с автомонтированием (сетевой шары!)?

Ну оно ж при первом cd примонтируется, а дальше автомонтирование не будет играть роли.

Или бывает ещё и автоотмонтирование сразу же по cd обратно?

А насчёт сети — да, наверное время изменится. Сейчас проверю. Другой комп в локалке, 1 гбит/с, примонтирован по sshfs.

CrX ★★★★★
()
Ответ на: комментарий от CrX

Ну оно ж при первом cd примонтируется

И это время запротоколируется.

Или бывает ещё и автоотмонтирование сразу же по cd обратно?

systemd, например, умеет отмонтировать по таймауту

anonymous
()
Ответ на: комментарий от anonymous

Ну в общем, тут надо определиться, что мы измеряем: время смены рабочего каталога (я до сих пор не понимаю, зачем, кстати), или время монтирования.


Вот, кстати, результаты по sshfs:

Empty loop is 24 seconds
cd loop is 351 seconds

17.55 микросекунд, соответственно, один cd в такой.

CrX ★★★★★
()
Ответ на: комментарий от CrX

/boot с автомонтированием, первый cd стабильно 0.06-0.07, следующие 0.00

$ sudo umount /boot
$ \time bash -c 'cd /boot'
0.00user 0.00system 0:00.07elapsed 1%CPU (0avgtext+0avgdata 3240maxresident)k
0inputs+0outputs (0major+154minor)pagefaults 0swaps
$ \time bash -c 'cd /boot'
0.00user 0.00system 0:00.00elapsed 50%CPU (0avgtext+0avgdata 3256maxresident)k
0inputs+0outputs (0major+155minor)pagefaults 0swaps
anonymous
()
Ответ на: комментарий от anonymous

Это время запуска bash, а не cd.

А, хотя на первое, конечно, повлияло монтирование.

Но причём тут кэширование и т.п. Это не время доступа, это время монтирования.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Но измерять именно время cd так некорректно.

А как корректно? Миллион cd в один и тот же каталог? Что это измеряет - скорость парсинга пути? Имеет ли это смысл для экспериментов с сетевым диском на ЯД?

anonymous
()
Ответ на: комментарий от anonymous

А как корректно?

Зависит от того, что мы хотим измерить.

Но в этом случае мы измеряем скорость запуска bash, а не «скорость cd», что бы это не значило.

Что это измеряет - скорость парсинга пути? Имеет ли это смысл для экспериментов с сетевым диском на ЯД?

На мой взгляд, измерение скорости перехода в каталог не имеет смысла вообще. Это надо ответа ТС ждать, нафига ему.

Но если допустить, что измерение этого в принципе имеет смысл, то да, оно имеет смысл в том числе и с сетевым диском на ЯД. Смотри выше, по sshfs с компом в локалке оно в три раза медленнее, чем на том же компе. С ЯД будет ещё медленнее. У меня такового нет, проверить не могу, но можешь сделать сам.

Ну а время монтирования лучше через mount замерять. Его можно даже в hyperfine завернуть, чтоб нормально статистику собрать. И umount, соответственно, который исполняется, но время для которого не считается.

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от CrX

Ну а время монтирования лучше через mount замерять.

(Авто)монтирование я привел как то, что может быть скрыто под обычным cd, доступом к каталогу.

anonymous
()
Ответ на: комментарий от anonymous

Почему тогда второй «запуск» 0.00?

Последний time, это запуск bash + общее выполнение всех cd

 ~ $ time bash -c 'time cd /data >/dev/null; time cd - >/dev/null'

real	0m0.000s
user	0m0.000s
sys	0m0.000s

real	0m0.000s
user	0m0.000s
sys	0m0.000s

real	0m0.004s
user	0m0.002s
sys	0m0.002s

Скрытие stdout, чтобы не учитывать время на вывод результатов cd в консоль.

dmitry237 ★★★★
()
Ответ на: комментарий от debugger

Зачем ты вызываешь внешнюю команду usr/bin/time когда есть встроенная команда баша time:

А я помню чтоли?
Был у меня какой то косяк со встроенной, не помню уже. С тех пор пользуюсь внешней.

n0mad ★★★
() автор топика
Ответ на: комментарий от CrX

И если не секрет, нафига оно тебе?

Ну ты замутил...
Ну для начала «cd /e» от безысходности. Я и без пробовал.
Хотя как тут уже посоветовали надо было сделать time cd /e
Хотя это обилие ньюансов меня БЕСИТ!
Я по привычке вывожу результат тайма в файл.
/usr/bin/time -o run-time.log <команда> - Работает!
И даже тут гуру посоветовал \time -o run-time.log <Команда> - Работает!
А вот time -o run-time.log <Команда> - не работает!
С этого давно и начиналось. Мне нужно было в файл вывести...

Нафига? А потому что $mc в каталог пол минуты заходит... (шифрованный)
Вот я и начал разбираться.

Я всё хочу добиться от убогого ЯДа, сохранение атрибутов файлов.
Даже топик такой открывал, все как всегда посмеялись.
Но я сделал предположение что файловые криптопрослойки - имеют свой механизм хранения атрибутов.

Начал эксперименты с cryfs и ecryptfs - которые есть в Debian.

5.5 часов заливал 65 гигов в первую.
Во вторую сильно быстрее, но /usr/bin/time в журнал записал не время а что то типа <EOF>
Потому что rsync ругнулся на слишком длинное имя файла, а время из консоли а я не сохранил.

В итоге провалились обе идеи. cryfs - тормозит не по детски, в том числе и при заходе в шифрованный каталог в $mc, секунд 40. Но это потому что mc делает df при каждой смене каталога. он всегда внизу панели пишет всего места и свободного для текущего. Так вот на df всё и тормозит. Потому что из консоли cd /p делается сразу а $df ./ думает секунд 40.
А вот ecryptfs не тормозит, но моя ФС не пролазит в его рамки. rsync рапортует: «Слишком длинное имя». можно конечно Десяток таких файлов вынести ближе к корню, но хочется чтобы работало так.

Вот с этого всё и началось, а так я в процессе реорганизации своего хозяйства из 9 накопителей, общим объёмом 20Т воткнутых в комп. А там ещё и ЯД...

n0mad ★★★
() автор топика
Ответ на: комментарий от anonymous

Во-вторых, время на cd будет 0.000, очевидно.

Если это точка монтирования с автомонтированием (сетевой шары!)? А если это сетевой диск? Играюсь здесь с ЯДом...

Так вот я с ЯДом и играюсь, но в режиме зеркала, а каталог это точка монтрования шифрованной ФС, при заходе на которую mc долго думает.

n0mad ★★★
() автор топика
Ответ на: комментарий от annulen

Какая разница, команде cd не интересно содержимое каталога

А вот bash-у интересно. Попробуй смонтировать что-то в каталог, потом перейти в него и размонтировать.

Aceler ★★★★★
()
Ответ на: комментарий от Aceler

А вот bash-у интересно. Попробуй смонтировать что-то в каталог, потом перейти в него и размонтировать.

Ну там inode каталога поменяется и прежний fd протухнет. От этого cd не превращется в операцию, требующую удалённого доступа

annulen ★★★★★
()
Ответ на: комментарий от annulen

Ну там inode каталога поменяется

Не поменяется, mount скажет что каталог занят и откажется размонтировать. Потому что inode каталога открывается. И по-моему, даже кешируется в dentry.

Aceler ★★★★★
()
Ответ на: комментарий от n0mad
  1. Вместо случайной расстановки закорючек методом тыка, лучше бы спросил, почему так. Всё просто — у time, встроенного в bash, нет аргумента -o. А у того, что в /usr/bin — есть.
  2. Это очень странный ответ, нафига. Допустим, mc заходит в каталог полминуты. Причём тут измерение времени cd? Как оно поможет? mc делает очень много чего при переходе в каталог, в том числе выводит его содержимое, вместе с размерами файлов, их атрибутами, свободным местом, и всякое такое.
  3. Наблюдается типичная проблема XY: вместо того, чтобы задать вопрос, который тебя действительно интересует (почему в mc смена каталога занимает 40 секунд, и что с этим делать при таких-то вводных), ты спрашиваешь, как измерить время исполнения cd в вакууме. Не надо так.
CrX ★★★★★
()

Я бы лучше сравнивал разные программы запустив их одновременно по количеству успешных выполнений за отведённое время, а не замерял время работы одной, потому что это не точно на мой взгляд.

drl
()

По делу в скрипте bash вполне может быть спекулятивное выполнение или компиляция после которого код уже как бы выполнен, а время уходит на чтение каталога или на компиляцию скрипта, так и получается что по факту сама команда не тратит времени нисколько.

drl
()
Последнее исправление: drl (всего исправлений: 3)
Ответ на: комментарий от drl

имхо Когда в bash выполняешь time cd он компилирует этот код в NOP.

?

Во-первых, у процесса есть атрибут «current working directory», или «cwd», который элементарно отслеживается снаружи через файл /proc/pid/cwd.

Во-вторых, cd без аргументов переходит в домашний каталог текущего пользователя, в чём легко убедиться по изменению соответствующего /proc/pid/cwd.

В-третьих, даже если домашний каталог уже является текущим рабочим каталогом, и, казалось бы, менять каталог не обязательно, баш всё равно выполняет сисколл chdir, в чём легко убедиться при помощи strace.

debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 1)
Ответ на: комментарий от CrX

Команды "cd /e" (как единого файла) нет (и даже быть не может из-за слеша — он недопустим в именах файлов).

? Говно вопрос:

$ mkdir 'cd '

$ cat <<EOF > 'cd /e'
> #!/bin/bash
> echo "Hello"
> sleep 1
> echo "world"
> EOF 

$ chmod a+x 'cd /e'

$ time "cd /e"
Hello
world

real	0m1.009s
user	0m0.002s
sys	0m0.006s
debugger ★★★★★
()
Последнее исправление: debugger (всего исправлений: 1)
Ответ на: комментарий от debugger

у процесса

whereis cd
🖕

Я к тому что сам по себе cd без последующего запуска процесса ничего не делает, bash осознав что это лишняя команда так оптимизирует и просто завершается.

drl
()
Последнее исправление: drl (всего исправлений: 1)
Ответ на: комментарий от CrX

Довольно таки ламерская программа:

#!/bin/bash
iterations=10000000

counter=$iterations
starttime=$(date +%s)
while [ $counter -ge 0 ]
do
    ((counter--))
done
endtime=$(date +%s)
echo Empty loop is $((endtime-starttime)) seconds

counter=$iterations
starttime=$(date +%s)
while [ $counter -ge 0 ]
do
    cd /usr/bin
    ((counter--))
    cd /usr/lib
done
endtime=$(date +%s)
echo cd loop is $((endtime-starttime)) seconds

$(date +%s) запускает новый процесс, и всё только ради того, чтобы вернуть время в секундах. Машина, конечно, должна работать, но человек должен думать. Запускать новый процесс только ради того, чтобы получить время — оверкилл, если можно обойтись простым чтением волшебной переменной SECONDS. Итого, улучшение раз:

#!/bin/bash
iterations=10000000

counter=$iterations
starttime=$SECONDS
while [ $counter -ge 0 ]
do
    ((counter--))
done
endtime=$SECONDS
echo Empty loop is $((endtime-starttime)) seconds

counter=$iterations
starttime=$SECONDS
while [ $counter -ge 0 ]
do
    cd /usr/bin
    ((counter--))
    cd /usr/lib
done
endtime=$SECONDS
echo cd loop is $((endtime-starttime)) seconds

Самый большой недостаток этой программы — секундное разрешение используемого таймера, из-за чего приходится крутить цикл аж 10 миллионов раз. Почему бы не пользовать таймер получше? Это улучшение два:

#!/bin/bash
iterations=10000000

counter=$iterations
starttime=$EPOCHREALTIME
while [ $counter -ge 0 ]
do
    ((counter--))
done
endtime=$EPOCHREALTIME
echo "Empty loop is $(echo $endtime - $starttime | bc) seconds"

counter=$iterations
starttime=$EPOCHREALTIME
while [ $counter -ge 0 ]
do
    cd /usr/bin
    ((counter--))
    cd /usr/lib
done
endtime=$EPOCHREALTIME
echo "cd loop is $(echo $endtime - $starttime | bc) seconds"

Из-за того, что баш не умеет оперировать с плавающими числами, пришлось вызывать внешний процесс, но это мера вынужденная (однако, читай дальше). Зато из-за лучшего (как минимум, на три порядка) разрешения таймера можно сократить количество итераций в 10 или даже 100 раз: с 10 миллионов до 100 тысяч, и получать те же результаты не за минуту, а за секунду.

А теперь самое главное: Зачем изобретать велосипед? В баше же есть специальная команда time, которая как раз предназначена для того, чтобы замерять время. Улучшение три:

#!/bin/bash
iterations=100000

counter=$iterations
time while [ $counter -ge 0 ]
do
    ((counter--))
done

counter=$iterations
time while [ $counter -ge 0 ]
do
    cd /usr/bin
    ((counter--))
    cd /usr/lib
done

Кстати, с командой time становится не нужным bc.

debugger ★★★★★
()
Ответ на: комментарий от CrX

Вместо случайной расстановки закорючек методом тыка, лучше бы спросил, почему так. Всё просто — у time, встроенного в bash, нет аргумента -o. А у того, что в /usr/bin — есть.

Это Вы к чему? Я знаю что у встроенного нет, поэтому и звал внешний, и не понимал как внешнему скормить башевый cd, гуру анонимус без срача всё сразу подсказал.

Это очень странный ответ, нафига. Допустим, mc заходит в каталог полминуты. Причём тут измерение времени cd? Как оно поможет? mc делает очень много чего при переходе в каталог, в том числе выводит его содержимое, вместе с размерами файлов, их атрибутами, свободным местом, и всякое такое.

Вот поэтому я и пытался абстрагироваться от mc с помощью cd; df

Наблюдается типичная проблема XY: вместо того, чтобы задать вопрос, который тебя действительно интересует (почему в mc смена каталога занимает 40 секунд, и что с этим делать при таких-то вводных), ты спрашиваешь, как измерить время исполнения cd в вакууме. Не надо так.

Странная у Вас логика. По моей логике я сначала пытаюсь нагуглить ответ и не отвлекать уважаемую общественность по мелочам, а вот если я этого не смог - я спрашиваю, по результатам предварительного расследования.

n0mad ★★★
() автор топика
Ответ на: комментарий от drl

Я к тому что сам по себе cd без последующего запуска процесса ничего не делает, bash осознав что это лишняя команда так оптимизирует и просто завершается.

Я тебе уже разжевал, что твои измышления неверны, и даже указал способ убедиться в этом. Не веришь мне — проверь сам.

debugger ★★★★★
()
Ответ на: комментарий от debugger

баш всё равно выполняет сисколл chdir, в чём легко убедиться при помощи strace

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

drl
()
Ответ на: комментарий от debugger

Получившаяся точность была достаточной для прикидки среднего с точностью до микросекунд. Бóльшая мне не требовалась. А главное, она и ТС’у то не требуется даже такая. Поэтому я не стал тратить время и лениво накидал «ламерский» вариант. О том, что его можно значительно доработать, я знал, но мне было лень. Если бы я собирался запускать это больше одного-двух раз — доработал бы, а так оно просто не стоило времени. Но спасибо, что сделали это за меня. Да, так действительно лучше.

Теперь у нас есть скрипт, делающий совершенно бесполезные измерения более эффективно :)

CrX ★★★★★
()
Последнее исправление: CrX (всего исправлений: 1)
Ответ на: комментарий от n0mad

Это Вы к чему? Я знаю что у встроенного нет, поэтому и звал внешний, и не понимал как внешнему скормить башевый cd, гуру анонимус без срача всё сразу подсказал.

«Гуру» анонимус подсказал разве что, как измерить время запуска bash. Это ещё дальше от того, что вам надо, чем было.

Странная у Вас логика. По моей логике я сначала пытаюсь нагуглить ответ и не отвлекать уважаемую общественность по мелочам, а вот если я этого не смог - я спрашиваю, по результатам предварительного расследования.

Логика как раз не странная — стоит всегда сообщать, какая проблема решается на самом деле, с перечислением предпринятых попыток решения. Иначе это прям типичнейшая проблема XY, как в этом треде.

CrX ★★★★★
()