speed_tester.py 2.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. #!/usr/bin/python3
  2. '''This script executes random-sized reads and writes to one or more block devices to test them.
  3. It will destroy the contents of the block device.'''
  4. import sys
  5. import os
  6. import mmap
  7. import random
  8. import time
  9. class BlockDevice:
  10. def __init__(self, path, sectorsize = 512):
  11. self.path = path
  12. self.dev = os.fdopen(os.open(path, os.O_RDWR | os.O_DIRECT | os.O_SYNC), "rb+", 0)
  13. self.sectorsize = sectorsize
  14. def write_block(self, first_sector, sector_count, seed):
  15. rnd = random.Random(seed)
  16. buffer = mmap.mmap(-1, sector_count * self.sectorsize)
  17. buffer.write(rnd.randbytes(sector_count * self.sectorsize))
  18. start = time.time()
  19. self.dev.seek(first_sector * self.sectorsize)
  20. self.dev.write(buffer)
  21. elapsed = time.time() - start
  22. speed = sector_count * self.sectorsize / elapsed / 1e6
  23. print("Wrote %16s, %8d, %8d, %8d, %8.3f MB/s" % (self.path, first_sector, sector_count, seed, speed))
  24. return speed
  25. def verify_block(self, first_sector, sector_count, seed):
  26. rnd = random.Random(seed)
  27. buffer = mmap.mmap(-1, sector_count * self.sectorsize)
  28. start = time.time()
  29. self.dev.seek(first_sector * self.sectorsize)
  30. self.dev.readinto(buffer)
  31. elapsed = time.time() - start
  32. speed = sector_count * self.sectorsize / elapsed / 1e6
  33. print("Verify %16s, %8d, %8d, %8d, %8.3f MB/s" % (self.path, first_sector, sector_count, seed, speed))
  34. buffer.seek(0)
  35. actual = buffer.read(sector_count * self.sectorsize)
  36. expected = rnd.randbytes(sector_count * self.sectorsize)
  37. if expected != actual:
  38. print("Compare error, device = %s, sectorsize = %d, first_sector = %d, sector_count = %d, seed = %d"
  39. % (self.path, self.sectorsize, first_sector, sector_count, seed))
  40. fname = "%d" % time.time()
  41. open(fname + ".expected", "wb").write(expected)
  42. open(fname + ".actual", "wb").write(actual)
  43. print("Saved data to %s.expected/actual" % fname)
  44. raise Exception("Compare error")
  45. return speed
  46. if __name__ == "__main__":
  47. blockdev = BlockDevice(sys.argv[1])
  48. seed = 1
  49. results = '# ReqSize(B) RdSpeed(MB/s) WrSpeed(MB/s)\n'
  50. for i in range(12):
  51. seed += 1
  52. seccount = 2**i
  53. wr_speeds = []
  54. rd_speeds = []
  55. samplecount = 8
  56. for i in range(samplecount):
  57. wr_speeds.append(blockdev.write_block(0, seccount, seed))
  58. time.sleep(0.2)
  59. rd_speeds.append(blockdev.verify_block(0, seccount, seed))
  60. time.sleep(0.2)
  61. # Get median
  62. wr_speeds.sort()
  63. rd_speeds.sort()
  64. wr_speed = wr_speeds[samplecount//2]
  65. rd_speed = rd_speeds[samplecount//2]
  66. results += '%8d %8.3f %8.3f\n' % (seccount * 512, rd_speed, wr_speed)
  67. print(results)