From a056e571b3a67e7da92f1e2a01ecc90864ea56b4 Mon Sep 17 00:00:00 2001 From: Artem Bityutskiy Date: Tue, 6 Nov 2012 15:41:29 +0200 Subject: [PATCH] BmapFlasher: improve flashing speed Improve flashing speed by switching to the 'noop' I/O scheduler for the block device we are flashing to. This gives ~20% write speed imporvement. Also limit the write buffering in order make the flashing - we do not need that and we better leave the memory for other applications. Change-Id: Ideca1b4ee786c91606e91813d2ffe451380506d3 Signed-off-by: Artem Bityutskiy --- bmaptools/BmapFlasher.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 2 deletions(-) diff --git a/bmaptools/BmapFlasher.py b/bmaptools/BmapFlasher.py index a657a85..4be30a1 100644 --- a/bmaptools/BmapFlasher.py +++ b/bmaptools/BmapFlasher.py @@ -187,10 +187,56 @@ class BmapFlasher: # Turn the block device file descriptor into a file object try: self._f_bdev = os.fdopen(self._f_bdev, "wb") - except IOError as err: + except OSError as err: os.close(self._f_bdev) raise Error("cannot open block device '%s': %s" \ - % (self._bdev_path, err.strerror)) + % (self._bdev_path, err)) + + def _tune_block_device(self): + """" Tune the block device for better performance: + 1. Switching to the 'noop' I/O scheduler if it is available. + Sequential write to the block device becomes a lot faster + comparing to CFQ. + 2. Limit the write buffering - we do not need the kernel to buffer + a lot of the data we send to the block device, because we write + sequentially. Limit the buffering. """ + + # Construct the path to the sysfs directory of our block device + st_rdev = os.fstat(self._f_bdev.fileno()).st_rdev + sysfs_base = "/sys/dev/block/%s:%s/" \ + % (os.major(st_rdev), os.minor(st_rdev)) + + # Switch to the 'noop' I/O scheduler + scheduler_path = sysfs_base + "queue/scheduler" + try: + f_scheduler = open(scheduler_path, "w") + except OSError as err: + # If we can't find the file, no problem, this stuff is just an + # optimization. + f_scheduler = None + pass + + if f_scheduler: + try: + f_scheduler.write("noop") + except IOError as err: + pass + f_scheduler.close() + + # Limit the write buffering + ratio_path = sysfs_base + "bdi/max_ratio" + try: + f_ratio = open(ratio_path, "w") + except OSError as err: + f_ratio = None + pass + + if f_ratio: + try: + f_ratio.write("1") + except IOError as err: + pass + f_ratio.close() def __init__(self, image_path, bdev_path, bmap_path = None): """ Initialize a class instance: @@ -366,6 +412,9 @@ class BmapFlasher: The 'verify' argument defines whether the SHA1 checksum has to be verified while writing. """ + if self.target_is_block_device: + self._tune_block_device() + if not self._f_bmap: self._write_entire_image(sync) return -- 2.7.4