1
0
Fork 0
pomodoro/archive/parallelizing-bash-scripts.md
2024-12-29 10:39:47 +03:00

98 lines
5.5 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Распараллеливание скриптов Bash
Рассмотрим последовательность действий, не зависящих друг от друга — это итерации циклов, или вызовы функций с параметрами.
Когда цикл один, или функция одна — это тривиальная задача для распараллеливания. Рассмотрим усложнённую модель с тремя
функциями и тремя параметрами для каждой — будем распараллеливать вызовы этих функций с использованием программы `xargs`.
Для решения вопроса об экранировании спецсимволов — сначала все параметры кодируем в HEX коды и после этого составляем с ними
строки — вызовы функций с параметрами. Далее обходим массив строк и выполняем функции в параллельном режиме. Внутри каждой из
них сначала декодируем параметры обратно и затем работаем с ними. Для наглядности замеряем общее время выполнения функций.
```bash
#!/bin/bash
#---------------------------------------------------------------------------;
# три функции с тремя параметрами
#---------------------------------------------------------------------------;
# первая функция с тремя параметрами
function first_func {
p1="$(decode "$1")"
p2="$(decode "$2")"
p3="$(decode "$3")"
echo "1 ${FUNCNAME[*]} [$p1] [$p2] [$p3]"
sleep 5 # эмуляция работы 5 секунд
}
# вторая функция с тремя параметрами
function second_func {
p1="$(decode "$1")"
p2="$(decode "$2")"
p3="$(decode "$3")"
echo "2 ${FUNCNAME[*]} [$p1] [$p2] [$p3]"
sleep 5 # эмуляция работы 5 секунд
}
# третья функция с тремя параметрами
function third_func {
p1="$(decode "$1")"
p2="$(decode "$2")"
p3="$(decode "$3")"
echo "3 ${FUNCNAME[*]} [$p1] [$p2] [$p3]"
sleep 5 # эмуляция работы 5 секунд
}
#---------------------------------------------------------------------------;
# вспомогательные функции и экспорт для дочерних процессов
#---------------------------------------------------------------------------;
# кодирование символов в HEX коды [U0000-UFFFF]
function encode { echo "$1" | uni2ascii -aE -qps; }
# декодирование символов из HEX кодов [U0000-UFFFF]
function decode { echo "$1" | ascii2uni -aE -q; }
# перечисление используемых функций в дочерних процессах bash
export -f decode first_func second_func third_func
#---------------------------------------------------------------------------;
# подготовка массива строк и вывод строк массива
#---------------------------------------------------------------------------;
# параметры могут содержать любые печатные символы или быть пустыми
param0=" \$param\""
param1=
param2='"$2"!="$1"'
# кодирование параметров
p0="$(encode "$param0")"
p1="$(encode "$param1")"
p2="$(encode "$param2")"
# массив строк — вызовы функций с параметрами
array[0]="first_func '$p0' '$p1' '$p2'"
array[1]="second_func '$p1' '$p2' '$p0'"
array[2]="third_func '$p2' '$p0' '$p1'"
# вывод строк массива для наглядности
printf '%s\n' "${array[@]}"
#---------------------------------------------------------------------------;
# параллельное выполнение функций и замер общего времени выполнения
#---------------------------------------------------------------------------;
# текущее время в миллисекундах
time_ms="$(date '+%s%3N')"
# вывод строк массива и вызов функции для каждой из них в параллельном режиме
printf '%s\0' "${array[@]}" | xargs -L1 -0 -P0 bash -c
# время работы в миллисекундах
echo "Общее время выполнения: $(($(date '+%s%3N') - time_ms)) мс."
```
## Вывод
Строки массива — вызовы функций с параметрами через пробелы в кавычках
```
first_func 'U0020U0024U0070U0061U0072U0061U006DU0022' '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022'
second_func '' 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022'
third_func 'U0022U0024U0032U0022U0021U003DU0022U0024U0031U0022' 'U0020U0024U0070U0061U0072U0061U006DU0022' ''
```
Параллельная работа функций, порядок может изменяться
```
3 third_func ["$2"!="$1"] [ $param"] []
2 second_func [] ["$2"!="$1"] [ $param"]
1 first_func [ $param"] [] ["$2"!="$1"]
```
Время работы функций в миллисекундах
```
Общее время выполнения: 5023 мс.
```
---
© Головин Г.Г., Код с комментариями, 2024