Az lenne a feladat, hogy a /proc/drbd file-ból kiolvassam, hogy egy disk szinkrnizációja hol tart.
El kezdtem megoldani a dolgot, itt egy példa, hogy hogyan néz ki a forrás amit elemezni kell:
/proc/drbd :
GIT-hash: bb447522fc9a87d0069b7e14f0234911ebdab0f7 build by phil@fat-tyre, 2008-11-12 16:40:33
1: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r---
ns:721924 nr:3746432 dw:4472324 dr:5040 al:52 bm:46 lo:0 pe:0 ua:0 ap:0
resync: used:0/61 hits:1217 misses:25 starving:0 dirty:0 changed:25
act_log: used:0/257 hits:139646 misses:52 starving:0 dirty:0 changed:52
2: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r---
ns:0 nr:12 dw:12 dr:60 al:0 bm:0 lo:0 pe:0 ua:0 ap:0
resync: used:0/61 hits:0 misses:0 starving:0 dirty:0 changed:0
act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0
3: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r---
ns:117416 nr:119924 dw:122652 dr:130921 al:25 bm:63 lo:0 pe:0 ua:0 ap:0
resync: used:0/61 hits:6891 misses:21 starving:0 dirty:0 changed:21
act_log: used:0/257 hits:325 misses:25 starving:0 dirty:0 changed:25
4: cs:Connected st:Primary/Secondary ds:UpToDate/UpToDate C r---
ns:0 nr:0 dw:0 dr:284 al:0 bm:0 lo:0 pe:0 ua:0 ap:0
resync: used:0/61 hits:0 misses:0 starving:0 dirty:0 changed:0
act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0
5: cs:SyncSource st:Primary/Secondary ds:UpToDate/Inconsistent C r---
ns:735360 nr:0 dw:0 dr:735360 al:0 bm:44 lo:0 pe:0 ua:0 ap:0
[>...................] sync'ed: 7.1% (9521/10239)M
finish: 0:58:02 speed: 2,656 (2,240) K/sec
resync: used:0/61 hits:45915 misses:45 starving:0 dirty:0 changed:45
act_log: used:0/257 hits:0 misses:0 starving:0 dirty:0 changed:0
Ezt ezzel értelmezem:
#!/usr/bin/perl -w
# A script inditasa: reg-test.pl
use strict;
my $dev = shift;
open (PROC, "<fake_proc");
my @p = <PROC>;
our $line;
for ( $a=0; $a<scalar(@p); $a++ ){
chomp($p[$a]);
if ( $p[$a] =~ /^\s*$dev:/ ) {
$line = $p[$a+2];
chomp($line);
}
}
close (PROC);
$line =~ s/[\s\t]*\[.*sync\'ed:\ *([\0-9\.]+)\%.*$/$1/;
print "$line\n";
maga a regexp, tehát: s/[\s\t]*\[.*sync\'ed:\ *([\0-9\.]+)\%.*$/$1/;
és innen kellene segítség, mivel azt szeretném, hogy ha a sorban nincs benne a "sync'ed" a sorban akkor cserélje le completted -re a sort. Tudom, hogy írhatnék még egy sort de azt nem akarom. Olvasgattam a http://perldoc.perl.org/ -on a perlre részt, de nem igazán értem, hogy ezt hogyan lehet.
Tehát aki tud kérem segítsen.
- 1279 megtekintés
Hozzászólások
szerintem igy lenne a legolvashatobb:
$line = ($line =~ s/sync\'ed:\ *([\0-9\.]+)/) ? $1 : 'Completed';
- A hozzászóláshoz be kell jelentkezni
A futásidő lényegesebb és itt tizedmásodpercekről van szó, mindenesetre jó gondolat
----
概略情報
- A hozzászóláshoz be kell jelentkezni
Az eredeti 4ms -es futáshoz képest ez így 5ms a két sor regexp 9ms -ével szemben, ez így jó:
$line = ( $line =~ /^\[.*sync\'ed:\ *([\0-9\.]+)\%.*$/ ? $1 : "completted" );
----
概略情報
- A hozzászóláshoz be kell jelentkezni
Már az eredetiben is gyanús, és itt is: mi a francnak van az s első paraméterében a 0 előtt backslash? (Ráadásul tudtommal szögletes zárójelen belül a . nem speciális, tehát azt se kéne takarni. Valamint nem látom, hogy miért nem használtok idézőjelet, és hogy hol van bezárva az s/// parancsban a "mire" sztring. Szóval szerintem ezeket a dolgokat kéne egy kicsit első körben finomítani :-) ).
Ui: Completed, egy t-vel :-)
- A hozzászóláshoz be kell jelentkezni
"Már az eredetiben is gyanús, és itt is: mi a francnak van az s első paraméterében a 0 előtt backslash? (Ráadásul tudtommal szögletes zárójelen belül a . nem speciális, tehát azt se kéne takarni. "
ctrl+c, ctrl+v (ezt én sem értem :s )
"Valamint nem látom, hogy miért nem használtok idézőjelet,"
Hol kellene?
A pillanatnyi kód:
#!/usr/bin/perl -w
use strict;
my $dev = shift;
open (PROC, "<fake_proc");
my @p = <PROC>;
close (PROC);
our $line;
for ( $a=0; $a<scalar(@p); $a++ ){
chomp($p[$a]);
$line = $p[$a+2] if ( $p[$a] =~ /^\s*$dev:/ );
}
$line = ( $line =~ /^[\s\t]*\[.*sync\'ed:\ *([0-9.]+)\%.*$/ ? $1 : "completted" );
print "$line\n";
Ez most így eléggé változatos futásidőket produkál 4-9ms között ezen még gyúrok, de azért az eredeti kérdés még megválaszolatlan
Segítsetek!
----
概略情報
- A hozzászóláshoz be kell jelentkezni
> Ez most így eléggé változatos futásidőket produkál 4-9ms között ezen még gyúrok
Nekem ez gyorsabbnak tűnik:
use strict;
my $dev = shift;
open PROC, '<', 'fake-proc.txt';
my @p; { local $/; @p = split( /[\r\n]+\s+(\d+): /, <PROC> ); }
close PROC;
print (($p[2*$dev] =~ /sync'ed:\s*([\d.]+)%/) ? $1: 'completed');
> az eredeti kérdés még megválaszolatlan
Nem jöttem rá, hogy mi az "eredeti kérdés". Talán tedd fel még egyszer.
- A hozzászóláshoz be kell jelentkezni
Ja igen ... :)
Szóval az a kérdésem, hogy a fenti regexp -et hogyan írhatnám át úgy, hogy ha a kérdéses sorban, benne van a "sync'ed" akkor az utánna álló számot adja vissza, ha nincs benne akkor a completted szöveget.
Jelenleg ebben a formában van a script:
#!/usr/bin/perl -w
use strict;
my $dev = shift;
my $line;
open (PROC, "<fake_proc");
my @p = <PROC>;
close (PROC);
for ( $a=0; $a<scalar(@p); $a++ ){
$line = ( $p[$a] =~ /^\s*$dev/ ? $p[$a+2] : $line );
}
$line = ( $line =~ /^[\s\t]*\[.*sync\'ed:\ *([0-9.]+)\%.*$/ ? $1 : "completted" );
print "$line\n";
Ez így 4ms futásidőt produkál (3.8 - 4.2 ms között)
----
概略情報
- A hozzászóláshoz be kell jelentkezni
> ha a kérdéses sorban, benne van a "sync'ed" akkor az utánna álló számot adja vissza, ha nincs benne akkor a completted szöveget.
Nem értem. Az általad bemásolt kódban pont ez van:
( $line =~ /^[\s\t]*\[.*sync\'ed:\ *([0-9.]+)\%.*$/ ? $1 : "completted" )
> Ez így 4ms futásidőt produkál (3.8 - 4.2 ms között)
Az én kódom mennyit produkál?
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy félreértem a feladatot, de ennyi miért nem elég?
print ($line=~/'ed: *([\d.]+)/ ? $1 : 'Completed') . '\n';
Minek a regexmotort terhelni felesleges kifejezésekkel? Aposztróf előfordulhat bárhol máshol?
- A hozzászóláshoz be kell jelentkezni
Jogos
----
概略情報
- A hozzászóláshoz be kell jelentkezni
Próbáld ki, milyen többmegás szövegen mindenféle feldolgozást végezni, gyorsan kiderül, mennyire fontos a motorra történő optimalizálás.
Ezen is lehet még :)
/'... *([\d.]+)/
(Sőt, régen dolgoztam perlben, lehet, hogy a /.../ helyett jobb a /.{3}/)
- A hozzászóláshoz be kell jelentkezni
Teszteld le, ez lehet, hogy még jobb:
/'.+?([\d.]+)/
vagy
/'[^\d]+([\d.]+)/
(Tapasztalataim alapján ez a kettő .NET-ben ugyanannyi idő alatt fut le.)
- A hozzászóláshoz be kell jelentkezni
Nem akartam teljesen átirni az eredetit, csak a regexp visszatérési értékére akartam felhívni a figyelmet. Egyébként én sem értem.
Az s viszont jogos, nem kell oda.
- A hozzászóláshoz be kell jelentkezni
És azt hiszem ez lesz a végleges megoldás:
#!/usr/bin/perl -w
use strict;
my $dev = shift;
my $line;
open (PROC, "</proc/drbd");
my @p = <PROC>;
close (PROC);
for ( $a=0; $a<scalar(@p); $a++ ){
$line = ( $p[$a] =~ /^\s*$dev/ ? $p[$a+2] : $line );
}
$line = ( $line =~ /ed: *([\d.]+)\%/ ? $1 : "completted" );
print "$line\n";
A futásidő kb 80%-át a file megnyitása és olvasása veszi el, úgyhogy nem lessz sokkal gyorsabb
----
概略情報
- A hozzászóláshoz be kell jelentkezni
> A futásidő kb 80%-át a file megnyitása és olvasása veszi el, úgyhogy nem lessz sokkal gyorsabb
Miért kéne hogy gyorsabb legyen?
- A hozzászóláshoz be kell jelentkezni
Azért, hogy akár másodpercenként is le lehessen kérdezni és hogy a lehető legkevesebb erőforrásba kerüljön
----
概略情報
- A hozzászóláshoz be kell jelentkezni
Ha csak az kell, hogy néha el lehessen indítani, akkor nem számít.
- A hozzászóláshoz be kell jelentkezni
Akar igy is lehet: (hasznalat: ./drbd.pl /proc/drbd):
drbd.pl:
#!/usr/bin/perl
use strict;
my $st;
while (<>) {
if (/^\s*([0-9]:)/) {
print "$1 - ";
$st = "completed";
}
$st = $1 if /sync'ed: *([0-9\.]+\%)/;
print "$st\n" if /act_log:/
}
- A hozzászóláshoz be kell jelentkezni
Megnéztem, mi ez a dbrd, de a for-ciklust nem értem...
Főleg, hogy ha a sebesség számít, akkor minek van egy rakás felesleges értékadás, az első találat után ki képne lépni a ciklusból.
Én egyetlen stringbe olvasnám be, aztán lehet regexelni...
/\n\s*$dev:.+\n.+\n.+?'.+?([\d]+)/
Az első sor eleje "GIT-hash", tehát biztos, hogy a device előtt van valami, így a device kikeresésére tökéletes a
/\n\s*$dev/
. Ezt és a következő sort nem kell figyelembe venni, erre jó a két
/.\n/
, főleg, hogy a
/./
nem illeszkedik a sorvégre, mert nem singleline keresés. Utána keresünk az aposztrófig, majd jön a százalékos érték (a százalékjelre teljesen felesleges keresni, a + harácsoló, amíg van számjegy vagy pont, addig "felzabálja".
Így a teljes kód ennyi:
#!/usr/bin/perl -w
use strict;
my $dev = shift;
local $/=undef;
open (PROC, "</proc/drbd");
my $p = <PROC>;
close (PROC);
print ($p=~/\n\s*$dev:.+\n.+\n.+?'.+?([\d]+)/?$1:'Completed').'\n';
Ez ugyanazt a hibát követi el, mint a Te kódod: ha a $dev-nek megfelelő blokk nem létezik, az eredménye "Completed".
(Remélem, nem írtam el, Windows alá nem raktam fel a Perlt.)
- A hozzászóláshoz be kell jelentkezni
Na ez eddig a legkompaktabb megoldás.
#!/usr/bin/perl -w
use strict;
my $dev = shift;
local $/=undef;
open (PROC, "</proc/drbd");
my $p = <PROC>;
close (PROC);
print ($p=~/\n\s*$dev:.+\n.+\n.+?'.+?([\d.]+)/?$1:'Completed');
print "\n";
sajnos nem gyorsabb, de akkor is remek.
"Ez ugyanazt a hibát követi el, mint a Te kódod: ha a $dev-nek megfelelő blokk nem létezik, az eredménye "Completed"."
ez nem gond, mivel már az eszköz elkészülte után fogom ezt a függvényt hívogatni.
----
概略情報
- A hozzászóláshoz be kell jelentkezni
Ami még számíthat sebességben:
1. A -w kapcsolónak jelen esetben semmi értelme, valójában a strict-nek sem.
2. Kihagyhatod az open/close párost (a fene tudja, lehet, hogy külön szálon lefut az open, amíg a perl fordít), ha a meghíváskor eleve a standard inputnak a /proc/drbd-t adod meg, valamint felesleges a shell-lel kitaláltatni, hogy ez perl kód:
perl holtartok.pl </proc/drbd
Így az egész ennyi:
my $dev = shift;
local $/=undef;
print (<>=~/\n\s*$dev:.+\n.+\n.+?'.+?([\d.]+)/?$1:'Completed').'\n';
Namost, ha idáig eljutottál, akkor, tekintve a kód hosszát - gyakorlatilag egyetlen regex - már simán átírhatod C-be is :), ezzel megúszod a perl fordítási idejét.
- A hozzászóláshoz be kell jelentkezni
Csak egy kurta megjegyzés: ha fontos a tempó, és regexpes manipuláció kell, érdemes megfontolni az áthangszerelést awk-ra. Pár éve játszottam saját teljesítménytesztekkel, és sokat vert a perlre.
- A hozzászóláshoz be kell jelentkezni
Az awk itt kevésbé rúg labdába, mert a soronkénti feldolgozásnak nem sok előnye lenne.
- A hozzászóláshoz be kell jelentkezni
Mosteztígyhogy? A fentebb polírozott kód mit csinál, ha nem soronként dolgoz fel?
Hogy előtte tömbbe is ír (így első ránézésre feleslegesen)?
- A hozzászóláshoz be kell jelentkezni
Sorry, nem vettem észre, hogy másik thread, annál már régen jobb a megoldás: http://hup.hu/node/75357#comment-835445
- A hozzászóláshoz be kell jelentkezni
Azert erdemes lenne megnezni egy ilyen kod sebesseget:
awk "/sync'ed/ { print \$3 }" /proc/drdb
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni
Ebben hol a device?
- A hozzászóláshoz be kell jelentkezni
Igaz, de en csak azt probaltam felvetni, hogy a perl az egy nagyon bonyolult, sokretu nyelv, tehat az interpretere is nagyon bonyolult, es sokretu. Ellenben az awk kimondottan erre van kihegyezve.
--
()=() Ki oda vagyik,
('Y') hol szall a galamb
C . C elszalasztja a
()_() kincset itt alant.
- A hozzászóláshoz be kell jelentkezni