LINUX.ORG.RU

Память в bash течёт как из ведра при переборе элементов массива

 , , , ,


1

3

Пример 1: счётчик итераций бесконечного цикла и объём используемой памяти (RSS)

#!/bin/bash
declare -A Array=( \
		['A']=1 \
		['B']=2 \
	)
let i=0
while true; do
	let ++i
	echo -n "${i}"; echo -n ' '
	ps -F -C 'bash' | grep "${0}" | tail -n 1 | awk '{print $6}'
done

$ bash test1.sh
1 1700
2 1704
3 1704
4 1704
5 1704
6 1704
7 1704
8 1704
9 1704
10 1704
…
2000 1704
…
10000 1708
^C


Пример 2: добавляем перебор элементов ассоциативного массива
#!/bin/bash
declare -A Array=( \
		['A']=1 \
		['B']=2 \
	)
let i=0
while true; do
	let ++i
	for key in "${!Array[@]}"; do
		echo -n ''
	done
	echo -n "${i}"; echo -n ' '
	ps -F -C 'bash' | grep "${0}" | tail -n 1 | awk '{print $6}'
done

$ bash test2.sh
1 1700
2 1704
3 1704
4 1704
5 1704
6 1704
7 1704
8 1704
9 1704
10 1704
…
45 1708
…
989 1736
990 1740
991 1740
992 1740
993 1740
994 1740
995 1740
996 1740
997 1740
998 1740
999 1740
1000 1740
…
2000 1768
…
10000 2024
^C

Скажите, пожалуйста, это я рукожоп или таки разработчики баша косорукие обезьяны?

Врёти, легковесные скрипты на баше наше всё!

anonymous ()

valgrind говорит:

==20566== All heap blocks were freed -- no leaks are possible
Скорее всего там управление памятью какое-то своеобразное.

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

Похоже на то. С обычными массивами там не лучше:

#!/bin/bash
declare -a Array=(1 2)
let i=0
while true; do
	let ++i
	for key in "${!Array[@]}"; do
		echo -n ''
	done
	echo -n "${i}"; echo -n ' '
	ps -F -C 'bash' | grep "${0}" | tail -n 1 | awk '{print $6}'
done

$ bash test3.sh
1 1700
2 1704
3 1704
4 1704
5 1704
6 1704
7 1704
8 1704
9 1704
10 1704
…
1000 1740
…
2000 1768
…
5000 1868
…
10000 2020
^C

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

Похоже там баг с перебором элементов по ключу, т.к. если убрать восклицательный знак в цикле for:

#!/bin/bash
declare -a Array=(1 2)
let i=0
while true; do
	let ++i
	for key in "${Array[@]}"; do
		echo -n ''
	done
	echo -n "${i}"; echo -n ' '
	ps -F -C 'bash' | grep "${0}" | tail -n 1 | awk '{print $6}'
done
Жора памяти при переборе значений массива не наблюдается.

h578b1bde ★☆ ()

Зачем делать это на баш? Другой скриптоты что-ли мало?

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

Скажите, пожалуйста, это я рукожоп...

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

ps -F -C 'bash' | grep "${0}" | tail -n 1 | awk '{print $6}'

которое работает правильно из-за случайности (у вас последний запущенный баш таки совпал с тем, который вы хотите замерить) на

ps -p $$ -o rss=
Zmicier ★★★★★ ()
Ответ на: комментарий от Zmicier

Есть немного

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

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

когда будете писать багрепорт

Пардон, не надо багрепорт, я перепроверил — на последнем ГНУ Баше не воспроизводится:

$ cat bash-memleak-test 
#!/bin/bash

array=( ['a']=1
        ['b']=2
        ['c']=3 )

while :; do
    : "${!array[@]}"
    if (( i % 10000 == 0)); then
        printf '%d' "$i"
        ps -p $$ -o rss=
    fi
    ((i++))
done

$ /bin/bash --version
GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
...

$ /bin/bash bash-memleak-test 
0 2844
10000 3448
20000 3640
30000 4068
40000 4236
50000 4664
60000 5012
70000 5240
80000 5636
90000 5816
100000 6236
^C

$ /opt/bash-4.4/bin/bash --version 
GNU bash, version 4.4.0(1)-release (x86_64-unknown-linux-gnu)
...

$ /opt/bash-4.4/bin/bash bash-memleak-test 
0 2760
10000 3024
20000 3024
30000 3024
40000 3024
50000 3024
60000 3024
70000 3024
80000 3024
90000 3024
100000 3024
^C
Zmicier ★★★★★ ()
Ответ на: комментарий от Zmicier

Не, ну то есть можно и даже небесполезно написать в багтрэкер вашей поставки ГНУ с целью засвидетельствовать (при условии, что еще никто не написал, разумеется), но лично мне лень.

Zmicier ★★★★★ ()
Последнее исправление: Zmicier (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.