random_tester.py 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  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. def verify_block(self, first_sector, sector_count, seed):
  25. rnd = random.Random(seed)
  26. buffer = mmap.mmap(-1, sector_count * self.sectorsize)
  27. start = time.time()
  28. self.dev.seek(first_sector * self.sectorsize)
  29. self.dev.readinto(buffer)
  30. elapsed = time.time() - start
  31. speed = sector_count * self.sectorsize / elapsed / 1e6
  32. print("Verify %16s, %8d, %8d, %8d, %8.3f MB/s" % (self.path, first_sector, sector_count, seed, speed))
  33. buffer.seek(0)
  34. actual = buffer.read(sector_count * self.sectorsize)
  35. expected = rnd.randbytes(sector_count * self.sectorsize)
  36. if expected != actual:
  37. print("Compare error, device = %s, sectorsize = %d, first_sector = %d, sector_count = %d, seed = %d"
  38. % (self.path, self.sectorsize, first_sector, sector_count, seed))
  39. fname = "%d" % time.time()
  40. open(fname + ".expected", "wb").write(expected)
  41. open(fname + ".actual", "wb").write(actual)
  42. print("Saved data to %s.expected/actual" % fname)
  43. raise Exception("Compare error")
  44. if __name__ == "__main__":
  45. blockdevs = []
  46. for path in sys.argv[1:]:
  47. sectorsize = 512
  48. if ':' in path:
  49. path, sectorsize = path.split(':')
  50. sectorsize = int(sectorsize)
  51. blockdevs.append(BlockDevice(path, sectorsize=sectorsize))
  52. maxsectors = 100000
  53. rnd = random.Random()
  54. while True:
  55. blocks = []
  56. start = 0
  57. while start + 256 < maxsectors:
  58. start = min(maxsectors, start + rnd.randint(0, 10000))
  59. dev = rnd.choice(blockdevs)
  60. count = rnd.randint(1, 256)
  61. seed = rnd.randint(1, 10000000)
  62. blocks.append((dev, start, count, seed))
  63. start += count
  64. print("Write / verify set size: %d" % len(blocks))
  65. random.shuffle(blocks)
  66. for dev, start, count, seed in blocks:
  67. dev.write_block(start, count, seed)
  68. random.shuffle(blocks)
  69. for dev, start, count, seed in blocks:
  70. dev.verify_block(start, count, seed)