Boru tamponunun dolu olup olmadığını nasıl anlarım?


11

Ben yazdım bazı Perl içine bir program çıktı borulama. Bu uzun süren bir süreç, bazen günler, bu yüzden darboğazlarımın nerede olduğunu öğrenmek ve onları açmaya çalışmak istiyorum. Veri benim betiği benim betiği işleyebilir daha hızlı piped olup olmadığını bilmek istiyorum. Eğer durum buysa, senaryomu ayarlamaya çalışacağım, ama ihtiyacım yoksa. Arabellek dolduğunda ayarlanan bir bayrak hakkında daha fazla yazmayı engelleyen bir konuşma görüyorum, ancak bu bayrağın ayarlanıp ayarlanmadığını veya ne sıklıkta ayarlandığını nasıl kontrol edebilirim? Herhangi bir fikir?


3
Bence sadece yazma süreci bilebilirdi.
enzotib

5
pvBoru zinciri boyunca bir yerde kullanmayı düşünebilirsiniz .
amfetamachine

Yanıtlar:


9

Perl betiğinizi bir sistem çağrısı izleme aracıyla izlerdim: strace(Linux), dtruss(OS X), ktrace(FreeBSD), truss(Solaris), vb. Hedef Perl betiğinizin okuma için ne kadar zaman harcadığını görmek olacaktır. stdin ve diğer programın stdout'una yazmak için ne kadar zaman harcıyor.

İşte bunu darboğaz olarak yazarla test ediyorum:

terminal 1$ gzip -c < /dev/urandom | cat > /dev/null

terminal 2$ ps auxw | egrep 'gzip|cat'
slamb    25311 96.0  0.0  2852  516 pts/0    R+   23:35   3:40 gzip -c
slamb    25312  0.8  0.0  2624  336 pts/0    S+   23:35   0:01 cat

terminal 2$ strace -p 25312 -s 0 -rT -e trace=read
Process 25312 attached - interrupt to quit
     0.000000 read(0, ""..., 4096) = 4096 <0.005207>
     0.005531 read(0, ""..., 4096) = 4096 <0.000051>

Buradaki ilk sayı, önceki sistem çağrısının başlamasından bu yana geçen süredir ve son sayı, sistem çağrısında harcanan zamandır. Böylece Perl ile bir araya gelmek için biraz işlem yapabiliriz ... [*]

terminal 2$ strace -p 25312 -s 0 -rT -e trace=read 2>&1 | perl -nle 'm{^\s*([\d.]+) read\(0, .*<([\d.]+)>} or next; $total_work += $1 - $last_wait; $total_wait += $2; $last_wait = $2; print "working for $total_work sec, waiting for $total_wait sec"; $last_wait = $2;'
working for 0 sec, waiting for 0.005592 sec
...
working for 0.305356 sec, waiting for 2.28624900000002 sec
...

terminal 2$ strace -p 25311 -s 0 -rT -e trace=write 2>&1 | perl -nle 'm{^\s*([\d.]+) write\(1, .*<([\d.]+)>} or next; $total_work += $1 - $last_wait; $total_wait += $2; $last_wait = $2; print "working for $total_work sec, waiting for $total_wait sec"; $last_wait = $2;'
...
working for 5.15862000000001 sec, waiting for 0.0555740000000007 sec
...

Her iki tarafı da aynı anda izleyen, sadece doğru dosya tanımlayıcıyı izleyen ve her saniye ya da daha uzun bir süre için diğerini beklediği güzel bir durum güncellemesi basan meraklılara gidebilir ve SystemTap veya DTrace komut dosyası oluşturabilirsiniz.

[*] - Uyarı: Diğer dosya tanımlayıcılarında okuma / yazma çağrılıyorsa kaba toplama işlemim pek doğru değil; bu durumda çalışma süresini hafife alacaktır.


Dtrace sürümü aslında oldukça düzgün.

terminal 1$ gzip -c < /dev/urandom | cat > /dev/null

terminal 2$ ps aux | egrep 'gzip| cat'
slamb    54189  95.8  0.0   591796    584 s006  R+   12:49AM  22:49.55 gzip -c
slamb    54190   0.4  0.0   599828    392 s006  S+   12:49AM   0:06.08 cat

terminal 2$ cat > pipe.d <<'EOF'
#!/usr/sbin/dtrace -qs

BEGIN
{
  start = timestamp;
  writer_blocked = 0;
  reader_blocked = 0;
}

tick-1s, END
{
  this->elapsed = timestamp - start;
  printf("since startup, writer blocked %3d%% of time, reader %3d%% of time\n",
         100 * writer_blocked / this->elapsed,
         100 * reader_blocked / this->elapsed);
}

syscall::write:entry
/pid == $1 && arg0 == 1/
{
  self->entry = timestamp;
}

syscall::write:return
/pid == $1 && self->entry != 0/
{
  writer_blocked += timestamp - self->entry;
  self->entry = 0;
}

syscall::read:entry
/pid == $2 && arg0 == 0/
{
  self->entry = timestamp;
}

syscall::read:return
/pid == $2 && self->entry != 0/
{
  reader_blocked += timestamp - self->entry;
  self->entry = 0;
}
EOF

terminal 2$ chmod u+x pipe.d
terminal 2$ sudo ./pipe.d 54189 54190
since startup, writer blocked   0% of time, reader  98% of time
since startup, writer blocked   0% of time, reader  99% of time
since startup, writer blocked   0% of time, reader  99% of time
since startup, writer blocked   0% of time, reader  99% of time
since startup, writer blocked   0% of time, reader  99% of time
^C
since startup, writer blocked   0% of time, reader  99% of time

Ve SystemTap sürümü:

terminal 1$ gzip -c /dev/urandom | cat > /dev/null

terminal 2$ ps auxw | egrep 'gzip| cat'
slamb     3405  109  0.0   4356   584 pts/1    R+   02:57   0:04 gzip -c /dev/urandom
slamb     3406  0.2  0.0  10848   588 pts/1    S+   02:57   0:00 cat

terminal 2$ cat > probes.stp <<'EOF'
#!/usr/bin/env stap

global start
global writer_pid
global writes
global reader_pid
global reads

probe begin {
  start = gettimeofday_us()
  writer_pid = strtol(argv[1], 10)
  reader_pid = strtol(argv[2], 10)
}

probe timer.s(1), end {
  elapsed = gettimeofday_us() - start
  printf("since startup, writer blocked %3d%% of time, reader %3d%% of time\n",
         100 * @sum(writes) / elapsed,
         100 * @sum(reads) / elapsed)
}

probe syscall.write.return {
  if (pid() == writer_pid && $fd == 1)
    writes <<< gettimeofday_us() - @entry(gettimeofday_us())
}

probe syscall.read.return {
  if (pid() == reader_pid && $fd == 0)
    reads <<< gettimeofday_us() - @entry(gettimeofday_us())
}
EOF

terminal 2$ chmod a+x probes.stp
terminal 2$ sudo ./pipe.stp 3405 3406
since startup, writer blocked   0% of time, reader  99% of time
...

6

pv -TCBoru hattınıza bir komut ekleyebilirsiniz :

cmd1 | pv -TC | cmd2

pvkendi arabelleğini kullanır ve -T1 saniyelik aralıklarla ortalama olarak ne kadar dolu olduğunu bildirir (varsayılan olarak).

Her zaman% 100 ise, bu cmd1, çıktı üretiminde cmd2tüketmekten daha hızlı demektir . Değilse, tam tersi. Boruların kendilerinin 64kB tutabileceğine dikkat edin.

Ayrıca -B, pvarabellek boyutunu belirtmek için de bakın . Birkaç pvs'yi aşağıdaki gibi kullanabilirsiniz :

$ cmd1 | pv -cCTrbN 'cmd1 -> cmd2' | cmd2 | pv -cCTrbN 'cmd2 -> cmd3' | cmd3
cmd1 -> cmd2: 1.92GiB { 53%} [ 387MiB/s]
cmd2 -> cmd3: 1.92GiB {  0%} [ 387MiB/s]
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.