#1 Le 20/04/2020, à 12:40
- Hizoka
[Retour d'experience] Repeter une suite de caractère
Bonjour à vous
Pour un besoin d'un script, il me fallait dupliquer une suite de caractère pour avoir une liste d'au moins 101 éléments.
Chaque élément pouvant être contenir plusieurs caractères.
J'ai donc fait mes petites commandes puis j'ai cherché sur le net pour voir comment faire mieux.
J'ai testé tout ce que j'ai trouvé mais si vous avez des remarques ou d'autres idées...
Et quitte à avoir fait tous ces tests, autant les partager, alors voilà...
Pour info :
Bash : GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Processeur : 4 x Intel Corde 2 Quad CPU Q9550 @ 2.83GHz
Ram : 8Go
Protocole :
J'ai exécuté 10 000 fois chaque commande via une boucle for :
for x in {0.10000}; do ...; done
J'ai chronométré 3 fois la boucle ci-dessus et j'ai gardé la valeur médiane.
ce qui donne :
# Boucle qui chronomètre 3 fois
for a in {1..3}
do
# Boucle lançant 10 000 la commande
time for x in {0..10000}
do
# Commande(s) testé(s)
unset Effect
for y in {0..26}
do
Effect+=(a b c d)
done
done
done
Afin de gagner du temps de lecture, je les ai trié du plus rapide au plus lent.
Nouveau gagnant : 0,781s
printf -vEffect 'a b c d %.s' {0..25}
Effect=(${Effect})
Nouveau gagnant : 1,107s
for y in {0..25}
do
Effect+='a b c d '
done
Effect=(${Effect})
La plus rapide : 1,489s
Et ce, malgré ce que j'ai pu lire disant que {0..25} étant une sous boucle ça ralentissait la boucle for.
unset Effect
for y in {0..25}
do
Effect+=(a b c d)
done
En modifiant un peu la boucle :
2,057s
unset Effect
y=26
while (( y-- ))
do
Effect+=(a b c d)
done
2,175s
unset Effect
for ((i=0; i<=25; i++))
do
Effect+=(a b c d)
done
2,320s
unset Effect
while [[ ${#Effect[@]} -le 100 ]]
do
Effect+=(a b c d)
done
2,475s
unset Effect x
until [[ $[x+=1] -gt 26 ]]
do
Effect+=(a b c d)
done
En s'éloignant de bash pur :
12.468s
Effect=$(printf "%26s")
Effect=(${Effect// /a b c d })
13,163s
Effect=($(printf 'a b c d %.0s' {0..25}))
14,435s
Effect=($(echo -e ''$_{1..26}'\ba b c d '))
17,540s
unset Effect
for y in $(seq 0 25)
do
Effect+=(a b c d)
done
0m24,594s
for a in {1..3}
do
time for x in {0..10000}
do
Effect=($(utfout "a b c d " -r 24))
done
done
28,741s
for a in {1..3}
do
time for x in {0..10000}
do
Effect=$(utfout "a b c d " -r 24)
Effect=(${Effect})
done
done
Avec awk :
30,101s
Effect=($(awk 'BEGIN {
while (z++ < 26) printf "a b c d "
}'))
30,230s
Effect=($(awk 'BEGIN {
OFS = "a b c d "
NF = 26
print
}'))
Autres tests horriblement longs :
54,661s
Effect=($(seq -f'a b c d %.0f' 101 | tr -d '\n0123456789'))
1m4,099s
Effect=$(printf "%26s")
Effect=($(sed "s/ /a b c d /g" <<< "${Effect}"))
2m20,910s
Effect=($(python -c 'print "a b c d "*(26)'))
6m9,799s
Effect=($(seq 1 26 | xargs -I {} printf "a b c d "))
Dernière modification par Hizoka (Le 21/04/2020, à 17:08)
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#2 Le 20/04/2020, à 14:26
- bruno
Re : [Retour d'experience] Repeter une suite de caractère
Salut,
Je ne comprends pas ton test.
Avec une boucle for :
time for y in {0..999}; do printf 'a b c d '; done
⇒
real 0m0,014s
user 0m0,009s
sys 0m0,005s
Avec une commande printf
time printf 'a b c d %.0s' {0..999}
⇒
real 0m0,003s
user 0m0,003s
sys 0m0,000s
#3 Le 20/04/2020, à 18:25
- kamaris
Re : [Retour d'experience] Repeter une suite de caractère
Oui, un unique printf est certainement une bonne idée, mais tout est dans l'affectation de variable après.
Si on fait
Effect=$(printf 'a b c d %.s' {0..26})
ça sera bien plus lourd que les meilleures versions de Hizoka.
En gros, j'obtiens les mêmes temps pour une boucle en x à 1000 unités au lieu de 10000.
Par contre, si on fait
printf -vEffect 'a b c d %.s' {0..26}
là, ça marche bien : j'ai une réduction d'un bon facteur 7.
Hors ligne
#4 Le 20/04/2020, à 18:36
- bruno
Re : [Retour d'experience] Repeter une suite de caractère
Je ne comprends toujours pas
time for y in {0..999}; do Effect+='a b c d '; done
real 0m0,012s
user 0m0,011s
sys 0m0,000s
time Effect=$(printf 'a b c d %.0s' {0..999})
real 0m0,007s
user 0m0,005s
sys 0m0,000s
Le problème ne serait-il pas au niveau de la méthode de test ?
#5 Le 20/04/2020, à 19:06
- kamaris
Re : [Retour d'experience] Repeter une suite de caractère
Pas vraiment, non : ça dépend plutôt de la taille de la chaine à engendrer.
Tu es parti sur 1000 répétitions de la chaine de base, alors que Hizoka partait sur 26 (ou 27) répétitions : je pense qu'il faut prendre ça comme une donnée.
Car si on augmente le nombre de répétitions, la rapidité de printf finit par l'emporter, mais pour un petit nombre de répétitions, ça n'est pas le cas :
$ time Effect=$(printf 'a b c d %.s' {0..26})
real 0m0,005s
user 0m0,000s
sys 0m0,005s
$ unset Effect; time for y in {0..26}; do Effect+='a b c d '; done
real 0m0,000s
user 0m0,000s
sys 0m0,000s
$
D'où l'intérêt de mettre une boucle en x autour de ça ensuite, pour faire monter les temps et pouvoir mieux comparer :
$ f() { time for x in {0..1000}; do unset Effect; Effect=$(printf 'a b c d %.s' {0..26}); done }
$ g() { time for x in {0..1000}; do unset Effect; for y in {0..26}; do Effect+='a b c d'; done; done }
$ h() { time for x in {0..1000}; do unset Effect; printf -vEffect 'a b c d %.s' {0..26}; done }
$ f
real 0m4,175s
user 0m1,156s
sys 0m3,067s
$ g
real 0m0,239s
user 0m0,223s
sys 0m0,000s
$ h
real 0m0,104s
user 0m0,095s
sys 0m0,000s
$
Hors ligne
#6 Le 20/04/2020, à 19:29
- Hizoka
Re : [Retour d'experience] Repeter une suite de caractère
Pas mal en effet
0,781s
for a in {1..3}
do
time for x in {0..10000}
do
printf -vEffect 'a b c d %.s' {0..25}
Effect=(${Effect})
done
done
@bruno
Je fais mes tests sur 10 000 boucles, pas 1 000.
Je vois que la création d'une liste est plus lourde que celle d'une variable.
0,515s
for a in {1..3}
do
time for x in {0..10000}
do
unset Effect
for y in {0..25}
do
Effect+='a b c d '
done
done
done
Si on fait sans liste.
1,107s
for a in {1..3}
do
time for x in {0..10000}
do
unset Effect
for y in {0..25}
do
Effect+='a b c d '
done
Effect=(${Effect})
done
done
Si on fait une variable puis une liste
1,455s
for a in {1..3}
do
time for x in {0..10000}
do
unset Effect
for y in {0..25}
do
Effect+=(a b c d)
done
done
done
Si on fait une liste directement
Dernière modification par Hizoka (Le 21/04/2020, à 17:05)
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#7 Le 21/04/2020, à 14:56
- LeoMajor
Re : [Retour d'experience] Repeter une suite de caractère
une suite de caractère pour avoir au moins 101 caractères.
bonjour,
lapsus concernant l'hypothèse de départ.
:~$ t=$(utfout "abcd" -r24)
:~$ wc -m <<<"$t"
101
for a in {1..3}
do
time { e=$(utfout "abcd" -r 24); effect=$(utfout "$e" -r 10000); }
time { e=$(utfout "a b c d " -r 25); effect=$(utfout "$e" -r 10000); }
done
real 0m0.623s
user 0m0.118s
sys 0m1.106s
real 0m1.267s
user 0m0.317s
sys 0m2.180s
real 0m0.661s
user 0m0.134s
sys 0m1.162s
real 0m1.228s
user 0m0.260s
sys 0m2.170s
real 0m0.621s
user 0m0.110s
sys 0m1.108s
real 0m1.345s
user 0m0.350s
sys 0m2.299s
Hors ligne
#8 Le 21/04/2020, à 17:02
- Hizoka
Re : [Retour d'experience] Repeter une suite de caractère
J'ai modifié l'intro qui n'était peut être pas assez claire :
...il me fallait dupliquer une suite de caractère pour avoir une liste d'au moins 101 éléments.
Chaque élément pouvant être contenir plusieurs caractères.
0m24,594s
for a in {1..3}
do
time for x in {0..10000}
do
Effect=($(utfout "a b c d " -r 24))
done
done
28,741s
for a in {1..3}
do
time for x in {0..10000}
do
Effect=$(utfout "a b c d " -r 24)
Effect=(${Effect})
done
done
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne
#9 Le 21/04/2020, à 18:46
- kamaris
Re : [Retour d'experience] Repeter une suite de caractère
Je pense que tu trouveras difficilement mieux que le couple
printf -v var … ; var=($var)
printf est une primitive du shell, qui gère son affectation de variable en interne.
Quant à la mise en tableau, cette forme est plus rapide que
read -a var <<<"$var"
qui est plus rapide que
mapfile -td' ' var <<<"$var"
Hors ligne
#10 Le 21/04/2020, à 19:31
- Hizoka
Re : [Retour d'experience] Repeter une suite de caractère
C'est pas mal en effet
Merci !
KDE Neon 64bits
Tous mes softs (MKVExtractorQt, HizoSelect, HizoProgress, Qtesseract, Keneric, Services menus...) sont sur github
Hors ligne