mirror of
https://github.com/sheumann/hush.git
synced 2024-12-21 23:29:34 +00:00
hdparm: simplify timing measurement (it wa the last last user
of setitimer in the tree). static.thousand 16 - -16 read_big_block 81 46 -35 getitimer 41 - -41 setitimer 47 - -47 __GI_setitimer 47 - -47 do_time 480 386 -94 ------------------------------------------------------------------------------ (add/remove: 0/4 grow/shrink: 0/2 up/down: 0/-280) Total: -280 bytes M miscutils/hdparm.c
This commit is contained in:
parent
0d3c6afc93
commit
c3122bca53
@ -429,10 +429,8 @@ static const char *const secu_str[] = {
|
||||
#define SIG 0x00ff /* signature location */
|
||||
#define SIG_VAL 0x00a5 /* signature value */
|
||||
|
||||
#define TIMING_MB 64
|
||||
#define TIMING_BUF_MB 1
|
||||
#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024)
|
||||
#define BUFCACHE_FACTOR 2
|
||||
|
||||
#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */
|
||||
|
||||
@ -505,6 +503,9 @@ struct globals {
|
||||
unsigned long hwif_ctrl;
|
||||
unsigned long hwif_irq;
|
||||
#endif
|
||||
#ifdef DO_FLUSHCACHE
|
||||
unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
|
||||
#endif
|
||||
};
|
||||
#define G (*(struct globals*)&bb_common_bufsiz1)
|
||||
struct BUG_G_too_big {
|
||||
@ -1342,22 +1343,17 @@ static void seek_to_zero(/*int fd*/ void)
|
||||
xlseek(fd, (off_t) 0, SEEK_SET);
|
||||
}
|
||||
|
||||
static int read_big_block(/*int fd,*/ char *buf)
|
||||
static void read_big_block(/*int fd,*/ char *buf)
|
||||
{
|
||||
int i;
|
||||
|
||||
i = read(fd, buf, TIMING_BUF_BYTES);
|
||||
if (i != TIMING_BUF_BYTES) {
|
||||
bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i);
|
||||
return 1;
|
||||
}
|
||||
xread(fd, buf, TIMING_BUF_BYTES);
|
||||
/* access all sectors of buf to ensure the read fully completed */
|
||||
for (i = 0; i < TIMING_BUF_BYTES; i += 512)
|
||||
buf[i] &= 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static unsigned long long do_blkgetsize(/*int fd*/ void)
|
||||
static unsigned long long dev_size_mb(/*int fd*/ void)
|
||||
{
|
||||
union {
|
||||
unsigned long long blksize64;
|
||||
@ -1365,85 +1361,88 @@ static unsigned long long do_blkgetsize(/*int fd*/ void)
|
||||
} u;
|
||||
|
||||
if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // returns bytes
|
||||
return u.blksize64 / 512;
|
||||
return u.blksize64 / (1024 * 1024);
|
||||
}
|
||||
xioctl(fd, BLKGETSIZE, &u.blksize32); // returns sectors
|
||||
return u.blksize32;
|
||||
return u.blksize32 / (2 * 1024);
|
||||
}
|
||||
|
||||
static void print_timing(unsigned t, double e)
|
||||
static void print_timing(unsigned long m, unsigned elapsed_us)
|
||||
{
|
||||
if (t >= e) /* more than 1MB/s */
|
||||
printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M');
|
||||
else
|
||||
printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k');
|
||||
unsigned sec = elapsed_us / 1000000;
|
||||
unsigned hs = (elapsed_us % 1000000) / 10000;
|
||||
|
||||
printf("%5lu MB in %u.%02u seconds = %lu kB/s\n",
|
||||
m, sec, hs,
|
||||
/* Trying to not overflow 32-bit arith in m * CONST
|
||||
* by keeping CONST not so big. + 1 prevents div-by-0. */
|
||||
(m * (1024 * 1000000 / (64*1024))) / (elapsed_us / (64*1024) + 1)
|
||||
// ~= (m * 1024 * 1000000) / elapsed_ms
|
||||
// = (m * 1024) / (elapsed_ms / 1000000)
|
||||
// = kb / elapsed_sec
|
||||
);
|
||||
}
|
||||
|
||||
static void do_time(int flag /*,int fd*/)
|
||||
/* flag = 0 time_cache, 1 time_device */
|
||||
static void do_time(int cache /*,int fd*/)
|
||||
/* cache=1: time cache: repeatedly read N MB at offset 0
|
||||
* cache=0: time device: linear read, starting at offset 0
|
||||
*/
|
||||
{
|
||||
static const struct itimerval thousand = {{1000, 0}, {1000, 0}};
|
||||
|
||||
struct itimerval itv;
|
||||
unsigned max_iterations, iterations;
|
||||
unsigned start; /* don't need to be long long */
|
||||
unsigned elapsed, elapsed2;
|
||||
unsigned max_iterations, total_MB, iterations;
|
||||
unsigned long total_MB;
|
||||
char *buf = xmalloc(TIMING_BUF_BYTES);
|
||||
|
||||
if (mlock(buf, TIMING_BUF_BYTES)) {
|
||||
bb_perror_msg("mlock");
|
||||
goto quit2;
|
||||
}
|
||||
if (mlock(buf, TIMING_BUF_BYTES))
|
||||
bb_perror_msg_and_die("mlock");
|
||||
|
||||
max_iterations = do_blkgetsize() / (2 * 1024) / TIMING_BUF_MB;
|
||||
/* Don't want to read past the end! */
|
||||
max_iterations = UINT_MAX;
|
||||
if (!cache)
|
||||
max_iterations = dev_size_mb() / TIMING_BUF_MB;
|
||||
|
||||
/* Clear out the device request queues & give them time to complete */
|
||||
/* Clear out the device request queues & give them time to complete.
|
||||
* NB: *small* delay. User is expected to have a clue and to not run
|
||||
* heavy io in parallel with measurements. */
|
||||
sync();
|
||||
sleep(2);
|
||||
if (flag == 0) { /* Time cache */
|
||||
sleep(1);
|
||||
if (cache) { /* Time cache */
|
||||
seek_to_zero();
|
||||
if (read_big_block(buf))
|
||||
goto quit;
|
||||
printf(" Timing buffer-cache reads: ");
|
||||
read_big_block(buf);
|
||||
printf("Timing buffer-cache reads: ");
|
||||
} else { /* Time device */
|
||||
printf(" Timing buffered disk reads: ");
|
||||
printf("Timing buffered disk reads:");
|
||||
}
|
||||
fflush(stdout);
|
||||
iterations = 0;
|
||||
/*
|
||||
* getitimer() is used rather than gettimeofday() because
|
||||
* it is much more consistent (on my machine, at least).
|
||||
*/
|
||||
//TODO: get rid of
|
||||
setitimer(ITIMER_REAL, &thousand, NULL);
|
||||
|
||||
/* Now do the timing */
|
||||
iterations = 0;
|
||||
start = monotonic_us();
|
||||
do {
|
||||
++iterations;
|
||||
if (flag == 0)
|
||||
if (cache)
|
||||
seek_to_zero();
|
||||
if (read_big_block(buf))
|
||||
goto quit;
|
||||
getitimer(ITIMER_REAL, &itv);
|
||||
elapsed = (1000 - itv.it_value.tv_sec) * 1000000
|
||||
- itv.it_value.tv_usec;
|
||||
read_big_block(buf);
|
||||
elapsed = (unsigned)monotonic_us() - start;
|
||||
++iterations;
|
||||
} while (elapsed < 3000000 && iterations < max_iterations);
|
||||
total_MB = iterations * TIMING_BUF_MB;
|
||||
if (flag == 0) {
|
||||
/* Now remove the lseek() and getitimer() overheads from the elapsed time */
|
||||
setitimer(ITIMER_REAL, &thousand, NULL);
|
||||
total_MB = (unsigned long)iterations * TIMING_BUF_MB;
|
||||
//printf(" elapsed:%u iterations:%u ", elapsed, iterations);
|
||||
if (cache) {
|
||||
/* Now remove the lseek() and monotonic_us() overheads
|
||||
* from elapsed */
|
||||
start = monotonic_us();
|
||||
do {
|
||||
seek_to_zero();
|
||||
getitimer(ITIMER_REAL, &itv);
|
||||
elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000
|
||||
- itv.it_value.tv_usec;
|
||||
elapsed2 = (unsigned)monotonic_us() - start;
|
||||
} while (--iterations);
|
||||
//printf(" elapsed2:%u ", elapsed2);
|
||||
elapsed -= elapsed2;
|
||||
total_MB *= BUFCACHE_FACTOR;
|
||||
total_MB *= 2; // BUFCACHE_FACTOR (why?)
|
||||
flush_buffer_cache();
|
||||
}
|
||||
print_timing(total_MB, elapsed / 1000000.0);
|
||||
quit:
|
||||
print_timing(total_MB, elapsed);
|
||||
munlock(buf, TIMING_BUF_BYTES);
|
||||
quit2:
|
||||
free(buf);
|
||||
}
|
||||
|
||||
@ -1688,7 +1687,6 @@ static void process_dev(char *devname)
|
||||
#ifndef WIN_FLUSHCACHE
|
||||
#define WIN_FLUSHCACHE 0xe7
|
||||
#endif
|
||||
static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
|
||||
#endif /* DO_FLUSHCACHE */
|
||||
args[2] = wcache ? 0x02 : 0x82;
|
||||
print_flag_on_off(get_wcache, "drive write-caching", wcache);
|
||||
@ -1749,7 +1747,7 @@ static void process_dev(char *devname)
|
||||
char buf[512];
|
||||
flush_buffer_cache();
|
||||
if (-1 == read(fd, buf, sizeof(buf)))
|
||||
bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1);
|
||||
bb_perror_msg("read(%d bytes) failed (rc=-1)", sizeof(buf));
|
||||
}
|
||||
#endif /* HDIO_DRIVE_CMD */
|
||||
|
||||
@ -1912,9 +1910,9 @@ static void process_dev(char *devname)
|
||||
ioctl_or_warn(fd, BLKRRPART, NULL);
|
||||
|
||||
if (do_ctimings)
|
||||
do_time(0 /*,fd*/); /* time cache */
|
||||
do_time(1 /*,fd*/); /* time cache */
|
||||
if (do_timings)
|
||||
do_time(1 /*,fd*/); /* time device */
|
||||
do_time(0 /*,fd*/); /* time device */
|
||||
if (do_flush)
|
||||
flush_buffer_cache();
|
||||
close(fd);
|
||||
|
Loading…
Reference in New Issue
Block a user