#!/usr/bin/perl # This script reads all sectors from a device # in $extent_size chunks and reports read speed. # Designed to be used on a PV to mark slow areas # with another script. use strict; use warnings; use Fcntl qw(:DEFAULT O_ASYNC O_DIRECT SEEK_END SEEK_SET); use Time::HiRes qw/clock_gettime CLOCK_MONOTONIC/; use v5.14; use BSD::Resource; $|=1; my $dev = $ARGV[0] || die("Usage: $0 device [extent_size]\n"); my $extent_size = $ARGV[1] || 4*1024*1024; sysopen(my $fh, $dev, O_RDONLY | O_DIRECT) or die "Couldn't open $dev\n"; # O_DIRECT requires some black magic for alignment # see http://www.perlmonks.org/bare/?node_id=653075 my $align = 4096; # linux 2.4 requires 4096, 2.6 ok with 512 my $buf = "\0"x($align+$extent_size); my $offset = unpack( "J", pack "p", $buf ) % $align; $offset = $align - $offset if $offset; my $size = sysseek $fh,0,SEEK_END; my $extents = $size / $extent_size; $extents == ~~$extents or die("Device size not multiple of extent size\n"); setpriority PRIO_PROCESS,0,-20; my $t1 = my $t2 = clock_gettime(CLOCK_MONOTONIC); for(my $i = 0; $i < $extents; $i++) { sysseek $fh,$i*$extent_size,SEEK_SET; sysread $fh,$buf,$extent_size,$offset; $t2 = clock_gettime(CLOCK_MONOTONIC); my $dt = $t2 - $t1; my $speed = $extent_size/1024/1024/$dt; $t1 = $t2; print "$i $speed $!\n"; }