1
Ohjelmointi, palvelimet ja muu edistyneempi käyttö / Vs: Skriptiajuri
« : 29.05.24 - klo:14.11 »
Silloin kun BASH luotiin sen käskyt tulkattiin muistista ja ne olivat nopeita - ihan niinkuin muissakin kielissä.
Nykyiset käskyt luetaan levyltä ennen tulkkaamista - epäilen kylläkin että ne ovat jo käännettyä koodia eikä niissä enää mitään tulkkaamista ole - mutta levyn lukeminen niissä kestää.
Ei sitä yksiomaan tuomita voi sillä on sillä paljon hyviäkin seurauksia. Mutta esitetäänpä yks esimerkki huonoista puolista: erotetaan tekstijononsta joku määräätävä sana. Totunnaiseti aikaansaadaan jotakin seuraavankaltaista:
Nopeilla käskyillä se on esimerkiksi (tämmöisiäkin tapoja on ziljoonia täysin erilaisia ja kullakin on omat erikoisominaisuutensa - mutta kaikki ne ovat nopeita):
---
Tein funktiosta version jonka toiminta-nopeus on sama mutta se toimii ikäänkuin parametri palautettaisiin eikä tulosta tarvitse pää-ohjelmassa lukea rakenteella $(kutsu). Skripti ja varsinkin sen kutsu ovat niin selväpiirteisiä että on käsittämätöntä ettei sellaisia käytännössä näy:
- etsintä voi alkaa edestä tai takaa - suunta riippuu etsintä-numeron merkistä. Toiminnan nopeuteen se ei kuitenkaan vaikuta.
- etsittävässä saa olla suurinpiirtein mitätahansa merkkejä - paitsi samanlaisia heittomerkkejä kuin alussa ja lopussa. Nykymuotisessa BASH:issa ei saa.
- Puhutaan vain ettei BASH osaa palauttaa funktioista parametreja ihan niinkuin se merkitsisi BASH:issa jotakin huonoa - päinvastoin se tarkoittaa hyvää. Jos esimerkiksi skriptissä on rivi:
etsi sana 3 lauseesta "9a 87b 654c 3(21)0d'ille!"
niin jos funktio:etsi on oikein tehty niin seuraavalla rivillä muuttujalla:sana on oikea arvo - eikä varmasti ole palautettu mitään - nyt voi vedota siihen ettei BASH osaa. Paikalle:sana voi kirjoittaa minkä tekstin hyvänsä ja seuraavalla rivillä se on saman-niminen muuttuja. Voi se alunperinkin olla muuttuja jonka arvo on aikaisemmin ollut mitävaan tai peräti ollut toisentyyppinen.
- suurta nopeutta ei voi mitata suoraan - eikä se oikein kannattaisikaan sillä skriptin suoritus-aika vaihtelee aina vähäsen - mutta yksi ratkaisu on muodostaa keskiarvoa sillä antaahan se ainakin jonkinlaisen ajan:
- välimuisti sotkee oikeaa tulosta, mutta pakkohan keskiarvoa on muodostaa koska tuollaista nopeutta ei voi mitata mitenkään toisin - eikä se välimuisti nopeuta sen enempää kuin 50%. Eikä se edes vaikuta täysmääräisenä heti ensimmäisellä kerralla. Kokeile. Sen kokeileminen tosin edellyttää ziljoonaa skripiä ja viikkojen pähkälyjä.
- mikäli sanoja erottaa joku muu merkki kuin välilyönti voi sen määrätä - seuraavassa sana-välinä on \n (elikä rivinsiirto). Mutta voi se tekstiäkin olla. Skripti ja sen kutsu ovat silloin:
---
Onhan niitä parempiakin funktioita kuin seuraava mutta kannattaa esittää sillä se kertoo että vanhat käskyt osaavat toimia regex:ien kanssa ihan suoraan: kyseessä on skriptauksen 'ikuisuus-ongelman ratkaiseminen' - erottaa jonkun laitteen tulosteesta haluttu lukema:
- tulosteen ei saa olettaa noudattavan minkäänlaista rakennetta - täytyy varautua siihen että siellä voi halutun tekstin lisäksi olla vaikka mitä:
- lmaisun:apu=${1#*$2[[:punct:]]} voisi kirjoittaa myös: apu=${1#*$2?}
[/code]
- mutta mitään semmoista ei voi tehdä joka ei kompastuisi johonkin.
---
Vanhojen käskyjen nopeus on tosiaan BASH:iksi tajuton - millisekuntien sijaan aletaan puhua mikrosekunneista. Mutuna sanoisin että vanhojen käskyjen kyvyt ovat kymmenesosa uusien käskyjen kyvyistä mutta koska ne ovat satakertaa nopeampia niin lopputulokseen päästään kymmenenkertaa nopeammin - ja vanhoista käskyistä voi tehdä kokonaisuuksia joiden kykyjä ei rajoita mikään muu kuin se mitä ohjelmoija osaa - ja ryhmä hidastuu vain vähän kun käskyjä tulee ryhmään lisää.
Ja vaikka vanhoilla käskyillä ei ole kytkimiä niin kyllä niitä mukaella voi -> esimerkiksi seuraava lause erottaa tekstijonosta neljännen tavun ( looppi hidastaa toimintaa suorituskertojen lisäksi noin 10% mutta noin nopeaan välimuistin vaikutus on olemattoman pieni - siis ajat muuttuvat lineaarisesti kun loopin n muuttuu). Kun 1 sekunti jaetaan 100000:lla saadaaan 10 mikrosekuntia:
- siis käskyssä: apu=${apu#* * * } on '* '-ryhmiä yhtä vähemmän kuin minkä palasen se erottaa
- sen 10% saa määriteltyä käskyllä: apu="1 2 3 4 5"; time for n in {1..100000}; do : ; done
- tuo käsky : on assemblerissa NOP elikä älä tee mitään. : kestää noin 3 mikrosekuntia ja echo noin 6 - joten jos echo:n sijaan tulos kirjoitetaan muuttujaan niin nopeus nousee kaksinkertaiseksi, nopeimmillaan 9:ksi mikrosekunniksi.
---
Tai toinen tapa jakaa:
- toki voidaan kirjoittaa myös: [!-+.e0-9] - ei se paljoa hidasta - mutta mitä enemmän tekee lisäyksiä jotta skripti toimisi erikois-tapauksissa oikein niin sitä useammmin kuitenkin karahtaa kiville. Jokatapauksessa tuolla [!-+.e0-9]:llä luvut voivat olla negatiivisia, desimaalilukuja tai tieteellistä esitysmuotoa.
- kyllä tuolla: melkein_yhdentekevää_mitä_tässä_on_kunhan_on_jotakin on rajoituksensa: sen ensimmäinen tai viimeinen merkki ei saa olla numero eivätkä ihan kaikki merkit kelpaa muutenkaan - ja ainakin jotakin siinä täytyy olla, vaikka vain välilyönti.
- myös edessä tai perässä voi ollamitätahansa tekstiä kunhan siinä ei ole numeroita. Muodostuvat etu- ja perä-välilyönnit vain poistetaan - esimerkiksi
***
- kaikki seuraavista ajoista ovat kone kohtaisia - nämä ajat ovat surkeasta läppäristä. Skriptit sensijaan toimivat missä koneessa tahansa.
Time-käskyn 1ms erottelukyky on uusille käskyille ihan riittävä - no melkein ainakin. Mutta vanhat käskyt vaatisivat vähintään 0.1 ms erottelukykyä jotta vanhoista käskyistä muodostettujen funktioiden nopeudesta saisi mielikuvan - ja joskus jopa 0.01 erottelukyky olisi tarpeen. Time-käskyä erottelukykyisempää käskyä ei kuitenkan ole mutta sellaisen voi tehdä itse - mutta se on kone riippuvainen joten time-käskyä kannattaa silti käyttää mikäli se näyttää enemmän kuin 1ms.
Tarkemman erottelukyvyn saa käskyn hetki=$(date +%s%N) avulla - se alkoi laskentansa kauan sitten ja on laskenut alkuhetken jälkeiset kellojaksot joten teoriassa se tietää tapahtumahetken nanosekunnin tarkkuudella - tämä on teoriaa mutta kuitenkin lyhyehkön ajan kuluessa se ei montaa nanosekuntia erehdy. Käyttöjärjestelmä se on kun aiheuttaa BASH:iille niin suuria horjahteluja ettei BASH tiedä kovin pitkään edes oikeaa millisekuntia - mutta 'nanosekunti'-kello pyörii kuitenkin kokoajan ja se on tarkinta mitä PC:sta löytyy.
- siis käskyllä: hetki=$(date +%s%N) BASH kysyy käyttöjärjestelmältä: mikäs nanosekunti on meneillään? Vastauksessa on 20 numeroa mikä riittää kertomaan mikä nanosekunti on meneillään vuodesta 1987 lähtien. Ja paljonko aikaa kysymykseen meneekään niin kahden kysymyksen väli on tarkka 'nanosekunnilleen'.
Ajoitetaanpa tällä menetelmällä nopea skripti:
anna nyt käsky: time kerro9 0.000000000000000001234 1.234567809123456
Saat ajoiksi esimerkiksi:
real 0m0,001s
user 0m0,001s
sys 0m0,000s
Miksi ajat erovat sillä 'nanosekunti' menetelmä on taatusti tarkka - mutta niin on varmasti myös time-käsky. Niiden täytyy siis mitata eri asioiden aika.
Tarkka ajoitus laskee aikaan myös sen ajan joka kestää että BASH alkaa yleensä toimimaan - siis jotta time-käskystä saisi saman ajan täytyisi noita time-käskyn kolmea arvon laskea yhteen jollain painotuksella. Nyt ei kannata luottaa siihen 0.5s arvoon mikä arvoksi on tähänasti arvioitu vaan määritellä se itse. Koska kyse on onnettoman lyhyestä ajasta täytynee se mitata loopissa - se kestää mutta onpahan sitten tarkempi - ja toivonmukaan luotettavampikin:
- ajoitetaan siis käsky : joka kutsuu kyllä tulkkia mutta tulkki palauttaa koodin NOP - älä tee mitään.
Kun vähennetään: 2307981 - 1953962/2 saadaan: 1331000 - siis noin 1.350ms. Tuntuu oikealta.
Nykyiset käskyt luetaan levyltä ennen tulkkaamista - epäilen kylläkin että ne ovat jo käännettyä koodia eikä niissä enää mitään tulkkaamista ole - mutta levyn lukeminen niissä kestää.
Ei sitä yksiomaan tuomita voi sillä on sillä paljon hyviäkin seurauksia. Mutta esitetäänpä yks esimerkki huonoista puolista: erotetaan tekstijononsta joku määräätävä sana. Totunnaiseti aikaansaadaan jotakin seuraavankaltaista:
Koodia: [Valitse]
echo '9 87 654 3210' | awk '{ print $3 }'
# tai:
awk '{ print $3 }' <(echo '9 87 654 3210')
#tai:
echo '9 87 654 3210' | cut -d' ' -f3
# tai:
cut -d' ' -f3 <(echo '9 87 654 3210')
- awk on tosi nopea ja monipuolinen - ja tämä awk:ille epä-edullinen esimerkki. Muuten cut on nopeampi. Nopeilla käskyillä se on esimerkiksi (tämmöisiäkin tapoja on ziljoonia täysin erilaisia ja kullakin on omat erikoisominaisuutensa - mutta kaikki ne ovat nopeita):
Koodia: [Valitse]
function tavu () { apu=$1; set ${@:2} ; eval echo \$$apu ;}
tavu 3 "9a 87b 654c 3210d"
Nopeusero on niin suuri ettei sitä saa kunnolla mitattua millään konstilla. Yksi perusteltu arvio on: 50* nopeus.---
Tein funktiosta version jonka toiminta-nopeus on sama mutta se toimii ikäänkuin parametri palautettaisiin eikä tulosta tarvitse pää-ohjelmassa lukea rakenteella $(kutsu). Skripti ja varsinkin sen kutsu ovat niin selväpiirteisiä että on käsittämätöntä ettei sellaisia käytännössä näy:
Koodia: [Valitse]
function etsi () { sana_matriisina=(${@:4}); read<<<${sana_matriisina[$2]} $1 ;}
etsi sana 3 lauseesta "9a 87b 654c 3(21)0d'ille!"
echo $sana # tämä echo on ihan vain varmistuksena että skripti on tehnyt sen mitä pitäisikin.
- heittomerkit voivat olla kovia, pehmeitä tai ne voivat puuttua kokonaan. - etsintä voi alkaa edestä tai takaa - suunta riippuu etsintä-numeron merkistä. Toiminnan nopeuteen se ei kuitenkaan vaikuta.
- etsittävässä saa olla suurinpiirtein mitätahansa merkkejä - paitsi samanlaisia heittomerkkejä kuin alussa ja lopussa. Nykymuotisessa BASH:issa ei saa.
- Puhutaan vain ettei BASH osaa palauttaa funktioista parametreja ihan niinkuin se merkitsisi BASH:issa jotakin huonoa - päinvastoin se tarkoittaa hyvää. Jos esimerkiksi skriptissä on rivi:
etsi sana 3 lauseesta "9a 87b 654c 3(21)0d'ille!"
niin jos funktio:etsi on oikein tehty niin seuraavalla rivillä muuttujalla:sana on oikea arvo - eikä varmasti ole palautettu mitään - nyt voi vedota siihen ettei BASH osaa. Paikalle:sana voi kirjoittaa minkä tekstin hyvänsä ja seuraavalla rivillä se on saman-niminen muuttuja. Voi se alunperinkin olla muuttuja jonka arvo on aikaisemmin ollut mitävaan tai peräti ollut toisentyyppinen.
- suurta nopeutta ei voi mitata suoraan - eikä se oikein kannattaisikaan sillä skriptin suoritus-aika vaihtelee aina vähäsen - mutta yksi ratkaisu on muodostaa keskiarvoa sillä antaahan se ainakin jonkinlaisen ajan:
Koodia: [Valitse]
function etsi () { sana_matriisina=(${@:4}); read<<<${sana_matriisina[$2]} $1 ;}
time { for n in {1..100000}; do etsi sana 3 lauseesta "9a 87b 654c 3(21)0d'ille!"; done ;}; echo $sana
- tämmöisessä looppi-virityksessä pitäisi laskea loopin vaikutus pois - mutta sen arvoksi voi olettaa tässätapauksessa 10% - mitattu on.- välimuisti sotkee oikeaa tulosta, mutta pakkohan keskiarvoa on muodostaa koska tuollaista nopeutta ei voi mitata mitenkään toisin - eikä se välimuisti nopeuta sen enempää kuin 50%. Eikä se edes vaikuta täysmääräisenä heti ensimmäisellä kerralla. Kokeile. Sen kokeileminen tosin edellyttää ziljoonaa skripiä ja viikkojen pähkälyjä.
- mikäli sanoja erottaa joku muu merkki kuin välilyönti voi sen määrätä - seuraavassa sana-välinä on \n (elikä rivinsiirto). Mutta voi se tekstiäkin olla. Skripti ja sen kutsu ovat silloin:
Koodia: [Valitse]
function etsi () { apu=${@:4}; sana_matriisina=(${apu//$5/ }); read<<<${sana_matriisina[$2]} $1 ;}
etsi sana 3 lauseesta "9a\n87\n654c\n3(21)0d'ille!" \n ; echo $sana
- jos raakaa nopeutta haluaa niin tässä on 20 mikrosekuntia kestävä versio, mutta muita ominaisuuksia sillä ei montaakaan olet:Koodia: [Valitse]
function hae_tavu () { sana_matriisina=(${@:2}); echo ${sana_matriisina[$1]} ;}
hae_tavu 3 "9a 87b 654c 3(21)0d'ille!"
---
Onhan niitä parempiakin funktioita kuin seuraava mutta kannattaa esittää sillä se kertoo että vanhat käskyt osaavat toimia regex:ien kanssa ihan suoraan: kyseessä on skriptauksen 'ikuisuus-ongelman ratkaiseminen' - erottaa jonkun laitteen tulosteesta haluttu lukema:
- tulosteen ei saa olettaa noudattavan minkäänlaista rakennetta - täytyy varautua siihen että siellä voi halutun tekstin lisäksi olla vaikka mitä:
Koodia: [Valitse]
function etsi_arvo () { apu=${1#*$2}; apu=${apu%%[!-+.0-9]*}; [[ $apu ]] || { apu=${1#*$2[[:punct:]]}; apu=${apu%%[!-+.0-9]*} ;}; echo $apu ;}
etsi_arvo ":::jännite215.61&'virta:-7.25 teho6.25 taajuus:123456.78" virta
- siis funktiokutsun viimeiseksi sanaksi (tässä: jännite) kirjoitetaan se jota haetaan. Koodia: [Valitse]
- lmaisu:apu=${1#*$2[[:punct:]]} - ihmiselle on ihan selvää mitä siinä yritetään - mutta on todella ihmeellistä että tulkki osaa tulkata sen oikein. - lmaisun:apu=${1#*$2[[:punct:]]} voisi kirjoittaa myös: apu=${1#*$2?}
[/code]
- mutta mitään semmoista ei voi tehdä joka ei kompastuisi johonkin.
---
Vanhojen käskyjen nopeus on tosiaan BASH:iksi tajuton - millisekuntien sijaan aletaan puhua mikrosekunneista. Mutuna sanoisin että vanhojen käskyjen kyvyt ovat kymmenesosa uusien käskyjen kyvyistä mutta koska ne ovat satakertaa nopeampia niin lopputulokseen päästään kymmenenkertaa nopeammin - ja vanhoista käskyistä voi tehdä kokonaisuuksia joiden kykyjä ei rajoita mikään muu kuin se mitä ohjelmoija osaa - ja ryhmä hidastuu vain vähän kun käskyjä tulee ryhmään lisää.
Ja vaikka vanhoilla käskyillä ei ole kytkimiä niin kyllä niitä mukaella voi -> esimerkiksi seuraava lause erottaa tekstijonosta neljännen tavun ( looppi hidastaa toimintaa suorituskertojen lisäksi noin 10% mutta noin nopeaan välimuistin vaikutus on olemattoman pieni - siis ajat muuttuvat lineaarisesti kun loopin n muuttuu). Kun 1 sekunti jaetaan 100000:lla saadaaan 10 mikrosekuntia:
Koodia: [Valitse]
apu="1 2 3 4 5"; time for n in {1..100000}; do apu=${apu#* * * }; echo ${apu%% *}; done
- siis käskyssä: apu=${apu#* * * } on '* '-ryhmiä yhtä vähemmän kuin minkä palasen se erottaa
- sen 10% saa määriteltyä käskyllä: apu="1 2 3 4 5"; time for n in {1..100000}; do : ; done
- tuo käsky : on assemblerissa NOP elikä älä tee mitään. : kestää noin 3 mikrosekuntia ja echo noin 6 - joten jos echo:n sijaan tulos kirjoitetaan muuttujaan niin nopeus nousee kaksinkertaiseksi, nopeimmillaan 9:ksi mikrosekunniksi.
---
Tai toinen tapa jakaa:
Koodia: [Valitse]
apu=6melkein_yhdentekevää_mitä_tässä_on_kunhan_on_jotakin2022; apu=${apu//[!0-9]/' '}; echo ${apu##* } #-> 2022
apu=6melkein_ yhdentekevää_mitä_tässä_on_kunhan_on_jotakin2022; apu=${apu//[!0-9]/' '}; echo ${apu%% *} #-> 6
- ^ toimii melkein samoin kuin !- toki voidaan kirjoittaa myös: [!-+.e0-9] - ei se paljoa hidasta - mutta mitä enemmän tekee lisäyksiä jotta skripti toimisi erikois-tapauksissa oikein niin sitä useammmin kuitenkin karahtaa kiville. Jokatapauksessa tuolla [!-+.e0-9]:llä luvut voivat olla negatiivisia, desimaalilukuja tai tieteellistä esitysmuotoa.
- kyllä tuolla: melkein_yhdentekevää_mitä_tässä_on_kunhan_on_jotakin on rajoituksensa: sen ensimmäinen tai viimeinen merkki ei saa olla numero eivätkä ihan kaikki merkit kelpaa muutenkaan - ja ainakin jotakin siinä täytyy olla, vaikka vain välilyönti.
- myös edessä tai perässä voi ollamitätahansa tekstiä kunhan siinä ei ole numeroita. Muodostuvat etu- ja perä-välilyönnit vain poistetaan - esimerkiksi
Koodia: [Valitse]
apu=6melkein_yhdentekevää_mitä_tässä_on_kunhan_on_jotakin2022jotain_muuta_tarinaa; apu=${apu//[!0-9]/' '}; apu=${apu%%+( )}; echo ${apu##* } #-> 2022
***
- kaikki seuraavista ajoista ovat kone kohtaisia - nämä ajat ovat surkeasta läppäristä. Skriptit sensijaan toimivat missä koneessa tahansa.
Time-käskyn 1ms erottelukyky on uusille käskyille ihan riittävä - no melkein ainakin. Mutta vanhat käskyt vaatisivat vähintään 0.1 ms erottelukykyä jotta vanhoista käskyistä muodostettujen funktioiden nopeudesta saisi mielikuvan - ja joskus jopa 0.01 erottelukyky olisi tarpeen. Time-käskyä erottelukykyisempää käskyä ei kuitenkan ole mutta sellaisen voi tehdä itse - mutta se on kone riippuvainen joten time-käskyä kannattaa silti käyttää mikäli se näyttää enemmän kuin 1ms.
Tarkemman erottelukyvyn saa käskyn hetki=$(date +%s%N) avulla - se alkoi laskentansa kauan sitten ja on laskenut alkuhetken jälkeiset kellojaksot joten teoriassa se tietää tapahtumahetken nanosekunnin tarkkuudella - tämä on teoriaa mutta kuitenkin lyhyehkön ajan kuluessa se ei montaa nanosekuntia erehdy. Käyttöjärjestelmä se on kun aiheuttaa BASH:iille niin suuria horjahteluja ettei BASH tiedä kovin pitkään edes oikeaa millisekuntia - mutta 'nanosekunti'-kello pyörii kuitenkin kokoajan ja se on tarkinta mitä PC:sta löytyy.
- siis käskyllä: hetki=$(date +%s%N) BASH kysyy käyttöjärjestelmältä: mikäs nanosekunti on meneillään? Vastauksessa on 20 numeroa mikä riittää kertomaan mikä nanosekunti on meneillään vuodesta 1987 lähtien. Ja paljonko aikaa kysymykseen meneekään niin kahden kysymyksen väli on tarkka 'nanosekunnilleen'.
Ajoitetaanpa tällä menetelmällä nopea skripti:
Koodia: [Valitse]
function kerro9 () {
[[ $1 =~ \. ]] && { apu=${1%%[1-9]*}; apu=${apu##*.}; exp1=${#apu}; luku1=${1//0.$apu/0.} ;} || { apu=${1##*[1-9]}; exp1=-${#apu}; [[ $apu ]] && luku1=${1:0: -$exp1} || luku1=$1 ;}
[[ $2 =~ \. ]] && { apu=${2%%[1-9]*}; apu=${apu##*.}; exp2=${#apu}; luku2=${2//0.$apu/0.} ;} || { apu=${2##*[1-9]}; exp2=-${#apu}; [[ $apu ]] && luku2=${2:0: -$exp2} || luku2=$2 ;}
int1=${luku1%%.*}
int2=${luku2%%.*}
apu2=$(($int1*$int2))
kokonaisia=${#apu2}
tulos=$((10#${luku1//./}*10#${luku2//./}))
tulo=000000000000000000$tulos'00000000000000000000'
tulo=${tulo:0:$((19-$exp1-$exp2))}.${tulo:$((19-$exp1-$exp2))}
apu=${tulo##+(0)}; [[ ${tulo//[^.]/} ]] && apu=${apu%%+(0)}; echo ${apu%.} ;}
function ajoita () { alku=0; alkuhetki=$(date +%s%N); sleep .1 ; loppuhetki=$(date +%%sN); alkuhetki=$(date +%s%N); $@ ; loppuhetki=$(date +%s%N); aika=$(($loppuhetki-$alkuhetki)); echo "toiminta \"$@\" kesti tälläkerralla: "$aika" ns" ;}
ajoita kerro9 0.000000000000000001234 1.234567809123456
saat ajaksi jotain: 2307981 nsanna nyt käsky: time kerro9 0.000000000000000001234 1.234567809123456
Saat ajoiksi esimerkiksi:
real 0m0,001s
user 0m0,001s
sys 0m0,000s
Miksi ajat erovat sillä 'nanosekunti' menetelmä on taatusti tarkka - mutta niin on varmasti myös time-käsky. Niiden täytyy siis mitata eri asioiden aika.
Tarkka ajoitus laskee aikaan myös sen ajan joka kestää että BASH alkaa yleensä toimimaan - siis jotta time-käskystä saisi saman ajan täytyisi noita time-käskyn kolmea arvon laskea yhteen jollain painotuksella. Nyt ei kannata luottaa siihen 0.5s arvoon mikä arvoksi on tähänasti arvioitu vaan määritellä se itse. Koska kyse on onnettoman lyhyestä ajasta täytynee se mitata loopissa - se kestää mutta onpahan sitten tarkempi - ja toivonmukaan luotettavampikin:
- ajoitetaan siis käsky : joka kutsuu kyllä tulkkia mutta tulkki palauttaa koodin NOP - älä tee mitään.
Koodia: [Valitse]
alku=0; for n in {1..1000}; do alkuhetki=$(date +%s%N); : ; loppuhetki=$(date +%s%N); alku=$(($alku+$((10#$loppuhetki-10#$alkuhetki)))); echo "keskiarvo $n mittauksesta: $(($alku/$n)) ns"; sleep 1; done
Tulokseksi tulee jotain seuraavan kaltaista: keskiarvo tuhannesta mittauksesta: 1953962 ns. Sriptien ajoituksessa täytyy tämä huomiida korjaksena - mutta korjaustermi ei ole tämä vaan tämän puolikas:Kun vähennetään: 2307981 - 1953962/2 saadaan: 1331000 - siis noin 1.350ms. Tuntuu oikealta.