aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-09-28 10:28:03 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-09-28 10:28:03 +0000
commitc3122bca53255799f052fcc0e911b68237faa12d (patch)
tree853664b39497f379970bf5b45b1986ae58de13f2
parent0d3c6afc93c8a6216fee9d60ecaa6a9d52687a65 (diff)
downloadbusybox-w32-c3122bca53255799f052fcc0e911b68237faa12d.tar.gz
busybox-w32-c3122bca53255799f052fcc0e911b68237faa12d.tar.bz2
busybox-w32-c3122bca53255799f052fcc0e911b68237faa12d.zip
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
-rw-r--r--miscutils/hdparm.c126
1 files changed, 62 insertions, 64 deletions
diff --git a/miscutils/hdparm.c b/miscutils/hdparm.c
index a3a5a7336..8a7204f29 100644
--- a/miscutils/hdparm.c
+++ b/miscutils/hdparm.c
@@ -429,10 +429,8 @@ static const char *const secu_str[] = {
429#define SIG 0x00ff /* signature location */ 429#define SIG 0x00ff /* signature location */
430#define SIG_VAL 0x00a5 /* signature value */ 430#define SIG_VAL 0x00a5 /* signature value */
431 431
432#define TIMING_MB 64
433#define TIMING_BUF_MB 1 432#define TIMING_BUF_MB 1
434#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024) 433#define TIMING_BUF_BYTES (TIMING_BUF_MB * 1024 * 1024)
435#define BUFCACHE_FACTOR 2
436 434
437#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */ 435#undef DO_FLUSHCACHE /* under construction: force cache flush on -W0 */
438 436
@@ -505,6 +503,9 @@ struct globals {
505 unsigned long hwif_ctrl; 503 unsigned long hwif_ctrl;
506 unsigned long hwif_irq; 504 unsigned long hwif_irq;
507#endif 505#endif
506#ifdef DO_FLUSHCACHE
507 unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
508#endif
508}; 509};
509#define G (*(struct globals*)&bb_common_bufsiz1) 510#define G (*(struct globals*)&bb_common_bufsiz1)
510struct BUG_G_too_big { 511struct BUG_G_too_big {
@@ -1342,22 +1343,17 @@ static void seek_to_zero(/*int fd*/ void)
1342 xlseek(fd, (off_t) 0, SEEK_SET); 1343 xlseek(fd, (off_t) 0, SEEK_SET);
1343} 1344}
1344 1345
1345static int read_big_block(/*int fd,*/ char *buf) 1346static void read_big_block(/*int fd,*/ char *buf)
1346{ 1347{
1347 int i; 1348 int i;
1348 1349
1349 i = read(fd, buf, TIMING_BUF_BYTES); 1350 xread(fd, buf, TIMING_BUF_BYTES);
1350 if (i != TIMING_BUF_BYTES) {
1351 bb_error_msg("read(%d bytes) failed (rc=%d)", TIMING_BUF_BYTES, i);
1352 return 1;
1353 }
1354 /* access all sectors of buf to ensure the read fully completed */ 1351 /* access all sectors of buf to ensure the read fully completed */
1355 for (i = 0; i < TIMING_BUF_BYTES; i += 512) 1352 for (i = 0; i < TIMING_BUF_BYTES; i += 512)
1356 buf[i] &= 1; 1353 buf[i] &= 1;
1357 return 0;
1358} 1354}
1359 1355
1360static unsigned long long do_blkgetsize(/*int fd*/ void) 1356static unsigned long long dev_size_mb(/*int fd*/ void)
1361{ 1357{
1362 union { 1358 union {
1363 unsigned long long blksize64; 1359 unsigned long long blksize64;
@@ -1365,85 +1361,88 @@ static unsigned long long do_blkgetsize(/*int fd*/ void)
1365 } u; 1361 } u;
1366 1362
1367 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // returns bytes 1363 if (0 == ioctl(fd, BLKGETSIZE64, &u.blksize64)) { // returns bytes
1368 return u.blksize64 / 512; 1364 return u.blksize64 / (1024 * 1024);
1369 } 1365 }
1370 xioctl(fd, BLKGETSIZE, &u.blksize32); // returns sectors 1366 xioctl(fd, BLKGETSIZE, &u.blksize32); // returns sectors
1371 return u.blksize32; 1367 return u.blksize32 / (2 * 1024);
1372} 1368}
1373 1369
1374static void print_timing(unsigned t, double e) 1370static void print_timing(unsigned long m, unsigned elapsed_us)
1375{ 1371{
1376 if (t >= e) /* more than 1MB/s */ 1372 unsigned sec = elapsed_us / 1000000;
1377 printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e, 'M'); 1373 unsigned hs = (elapsed_us % 1000000) / 10000;
1378 else 1374
1379 printf("%4d MB in %.2f seconds = %.2f %cB/sec\n", t, e, t / e * 1024, 'k'); 1375 printf("%5lu MB in %u.%02u seconds = %lu kB/s\n",
1376 m, sec, hs,
1377 /* Trying to not overflow 32-bit arith in m * CONST
1378 * by keeping CONST not so big. + 1 prevents div-by-0. */
1379 (m * (1024 * 1000000 / (64*1024))) / (elapsed_us / (64*1024) + 1)
1380 // ~= (m * 1024 * 1000000) / elapsed_ms
1381 // = (m * 1024) / (elapsed_ms / 1000000)
1382 // = kb / elapsed_sec
1383 );
1380} 1384}
1381 1385
1382static void do_time(int flag /*,int fd*/) 1386static void do_time(int cache /*,int fd*/)
1383/* flag = 0 time_cache, 1 time_device */ 1387/* cache=1: time cache: repeatedly read N MB at offset 0
1388 * cache=0: time device: linear read, starting at offset 0
1389 */
1384{ 1390{
1385 static const struct itimerval thousand = {{1000, 0}, {1000, 0}}; 1391 unsigned max_iterations, iterations;
1386 1392 unsigned start; /* don't need to be long long */
1387 struct itimerval itv;
1388 unsigned elapsed, elapsed2; 1393 unsigned elapsed, elapsed2;
1389 unsigned max_iterations, total_MB, iterations; 1394 unsigned long total_MB;
1390 char *buf = xmalloc(TIMING_BUF_BYTES); 1395 char *buf = xmalloc(TIMING_BUF_BYTES);
1391 1396
1392 if (mlock(buf, TIMING_BUF_BYTES)) { 1397 if (mlock(buf, TIMING_BUF_BYTES))
1393 bb_perror_msg("mlock"); 1398 bb_perror_msg_and_die("mlock");
1394 goto quit2;
1395 }
1396 1399
1397 max_iterations = do_blkgetsize() / (2 * 1024) / TIMING_BUF_MB; 1400 /* Don't want to read past the end! */
1401 max_iterations = UINT_MAX;
1402 if (!cache)
1403 max_iterations = dev_size_mb() / TIMING_BUF_MB;
1398 1404
1399 /* Clear out the device request queues & give them time to complete */ 1405 /* Clear out the device request queues & give them time to complete.
1406 * NB: *small* delay. User is expected to have a clue and to not run
1407 * heavy io in parallel with measurements. */
1400 sync(); 1408 sync();
1401 sleep(2); 1409 sleep(1);
1402 if (flag == 0) { /* Time cache */ 1410 if (cache) { /* Time cache */
1403 seek_to_zero(); 1411 seek_to_zero();
1404 if (read_big_block(buf)) 1412 read_big_block(buf);
1405 goto quit; 1413 printf("Timing buffer-cache reads: ");
1406 printf(" Timing buffer-cache reads: ");
1407 } else { /* Time device */ 1414 } else { /* Time device */
1408 printf(" Timing buffered disk reads: "); 1415 printf("Timing buffered disk reads:");
1409 } 1416 }
1410 fflush(stdout); 1417 fflush(stdout);
1411 iterations = 0; 1418
1412 /*
1413 * getitimer() is used rather than gettimeofday() because
1414 * it is much more consistent (on my machine, at least).
1415 */
1416//TODO: get rid of
1417 setitimer(ITIMER_REAL, &thousand, NULL);
1418 /* Now do the timing */ 1419 /* Now do the timing */
1420 iterations = 0;
1421 start = monotonic_us();
1419 do { 1422 do {
1420 ++iterations; 1423 if (cache)
1421 if (flag == 0)
1422 seek_to_zero(); 1424 seek_to_zero();
1423 if (read_big_block(buf)) 1425 read_big_block(buf);
1424 goto quit; 1426 elapsed = (unsigned)monotonic_us() - start;
1425 getitimer(ITIMER_REAL, &itv); 1427 ++iterations;
1426 elapsed = (1000 - itv.it_value.tv_sec) * 1000000
1427 - itv.it_value.tv_usec;
1428 } while (elapsed < 3000000 && iterations < max_iterations); 1428 } while (elapsed < 3000000 && iterations < max_iterations);
1429 total_MB = iterations * TIMING_BUF_MB; 1429 total_MB = (unsigned long)iterations * TIMING_BUF_MB;
1430 if (flag == 0) { 1430 //printf(" elapsed:%u iterations:%u ", elapsed, iterations);
1431 /* Now remove the lseek() and getitimer() overheads from the elapsed time */ 1431 if (cache) {
1432 setitimer(ITIMER_REAL, &thousand, NULL); 1432 /* Now remove the lseek() and monotonic_us() overheads
1433 * from elapsed */
1434 start = monotonic_us();
1433 do { 1435 do {
1434 seek_to_zero(); 1436 seek_to_zero();
1435 getitimer(ITIMER_REAL, &itv); 1437 elapsed2 = (unsigned)monotonic_us() - start;
1436 elapsed2 = (1000 - itv.it_value.tv_sec) * 1000000
1437 - itv.it_value.tv_usec;
1438 } while (--iterations); 1438 } while (--iterations);
1439 //printf(" elapsed2:%u ", elapsed2);
1439 elapsed -= elapsed2; 1440 elapsed -= elapsed2;
1440 total_MB *= BUFCACHE_FACTOR; 1441 total_MB *= 2; // BUFCACHE_FACTOR (why?)
1441 flush_buffer_cache(); 1442 flush_buffer_cache();
1442 } 1443 }
1443 print_timing(total_MB, elapsed / 1000000.0); 1444 print_timing(total_MB, elapsed);
1444 quit:
1445 munlock(buf, TIMING_BUF_BYTES); 1445 munlock(buf, TIMING_BUF_BYTES);
1446 quit2:
1447 free(buf); 1446 free(buf);
1448} 1447}
1449 1448
@@ -1688,7 +1687,6 @@ static void process_dev(char *devname)
1688#ifndef WIN_FLUSHCACHE 1687#ifndef WIN_FLUSHCACHE
1689#define WIN_FLUSHCACHE 0xe7 1688#define WIN_FLUSHCACHE 0xe7
1690#endif 1689#endif
1691 static unsigned char flushcache[4] = { WIN_FLUSHCACHE, 0, 0, 0 };
1692#endif /* DO_FLUSHCACHE */ 1690#endif /* DO_FLUSHCACHE */
1693 args[2] = wcache ? 0x02 : 0x82; 1691 args[2] = wcache ? 0x02 : 0x82;
1694 print_flag_on_off(get_wcache, "drive write-caching", wcache); 1692 print_flag_on_off(get_wcache, "drive write-caching", wcache);
@@ -1749,7 +1747,7 @@ static void process_dev(char *devname)
1749 char buf[512]; 1747 char buf[512];
1750 flush_buffer_cache(); 1748 flush_buffer_cache();
1751 if (-1 == read(fd, buf, sizeof(buf))) 1749 if (-1 == read(fd, buf, sizeof(buf)))
1752 bb_perror_msg("read(%d bytes) failed (rc=%d)", sizeof(buf), -1); 1750 bb_perror_msg("read(%d bytes) failed (rc=-1)", sizeof(buf));
1753 } 1751 }
1754#endif /* HDIO_DRIVE_CMD */ 1752#endif /* HDIO_DRIVE_CMD */
1755 1753
@@ -1912,9 +1910,9 @@ static void process_dev(char *devname)
1912 ioctl_or_warn(fd, BLKRRPART, NULL); 1910 ioctl_or_warn(fd, BLKRRPART, NULL);
1913 1911
1914 if (do_ctimings) 1912 if (do_ctimings)
1915 do_time(0 /*,fd*/); /* time cache */ 1913 do_time(1 /*,fd*/); /* time cache */
1916 if (do_timings) 1914 if (do_timings)
1917 do_time(1 /*,fd*/); /* time device */ 1915 do_time(0 /*,fd*/); /* time device */
1918 if (do_flush) 1916 if (do_flush)
1919 flush_buffer_cache(); 1917 flush_buffer_cache();
1920 close(fd); 1918 close(fd);