Re: [PATCH v4 1/3] scripts/simplebench: compare write request performance

2020-07-13 Thread Vladimir Sementsov-Ogievskiy

12.07.2020 20:49, Andrey Shinkevich wrote:

The script 'bench_write_req.py' allows comparing performances of write
request for two qemu-img binary files.
An example with (qemu-img binary 1) and without (qemu-img binary 2) the
applied patch "qcow2: skip writing zero buffers to empty COW areas"
(git commit ID: c8bb23cbdbe32f5) has the following results:

SSD:
-  ---  ---
  
  0.34 +- 0.01 10.57 +- 0.96
 0.33 +- 0.01 9.15 +- 0.85
   0.33 +- 0.00 8.72 +- 0.05
  7.43 +- 1.19 14.35 +- 1.00
-  ---  ---
HDD:
-  ---  ---
  
  32.61 +- 1.1755.11 +- 1.15
 54.28 +- 8.8260.11 +- 2.76
   57.93 +- 0.4758.53 +- 0.51
  11.47 +- 0.9417.29 +- 4.40
-  ---  ---

Suggested-by: Denis V. Lunev 
Suggested-by: Vladimir Sementsov-Ogievskiy 
Signed-off-by: Andrey Shinkevich 


Andrey wants to drop 02,03 in v5, so this patch is a candidate for v5. Below my 
notes.


---
  scripts/simplebench/bench_write_req.py | 173 +
  1 file changed, 173 insertions(+)
  create mode 100755 scripts/simplebench/bench_write_req.py

diff --git a/scripts/simplebench/bench_write_req.py 
b/scripts/simplebench/bench_write_req.py
new file mode 100755
index 000..a285ef1
--- /dev/null
+++ b/scripts/simplebench/bench_write_req.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python3
+#
+# Test to compare performance of write requests for two qemu-img binary files.


Let's note that patch is intended to check benefit of c8bb23cbdbe
"qcow2: skip writing zero buffers to empty COW areas"


+#
+# Copyright (c) 2020 Virtuozzo International GmbH.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+
+import sys
+import os
+import subprocess
+import simplebench
+
+
+def bench_func(env, case):
+""" Handle one "cell" of benchmarking table. """
+return bench_write_req(env['qemu_img'], env['image_name'],
+   case['block_size'], case['block_offset'],
+   case['requests'])
+
+
+def qemu_img_pipe(*args):
+'''Run qemu-img and return its output'''
+subp = subprocess.Popen(list(args),
+stdout=subprocess.PIPE,
+stderr=subprocess.STDOUT,
+universal_newlines=True)
+exitcode = subp.wait()
+if exitcode < 0:
+sys.stderr.write('qemu-img received signal %i: %s\n'
+ % (-exitcode, ' '.join(list(args
+return subp.communicate()[0]
+
+
+def bench_write_req(qemu_img, image_name, block_size, block_offset, requests):
+"""Benchmark write requests
+
+The function creates a QCOW2 image with the given path/name and fills it
+with random data optionally. 


No, it doesn't fill..


+ Then it runs the 'qemu-img bench' command and
+makes series of write requests on the image clusters. Finally, it returns
+the total time of the write operations on the disk.
+
+qemu_img -- path to qemu_img executable file
+image_name   -- QCOW2 image name to create
+block_size   -- size of a block to write to clusters
+block_offset -- offset of the block in clusters
+requests -- number of write requests per cluster
+
+Returns {'seconds': int} on success and {'error': str} on failure.
+Return value is compatible with simplebench lib.
+"""
+
+if not os.path.isfile(qemu_img):
+print(f'File not found: {qemu_img}')
+sys.exit(1)
+
+image_dir = os.path.dirname(os.path.abspath(image_name))
+if not os.path.isdir(image_dir):
+print(f'Path not found: {image_name}')
+sys.exit(1)
+
+cluster_size = 1024 * 1024
+image_size = 1024 * cluster_size
+seek = 4
+dd_count = int(image_size / cluster_size) - seek


seek and dd_count are unused


+
+args_create = [qemu_img, 'create', '-f', 'qcow2', '-o',
+   f'cluster_size={cluster_size}',
+   image_name, str(image_size)]
+
+count = requests * int(image_size / cluster_size)


requests is number of requests per cluster..


+step = str(cluster_size)


but step is one cluster. So, we have several requests per cluster, but 

[PATCH v4 1/3] scripts/simplebench: compare write request performance

2020-07-12 Thread Andrey Shinkevich
The script 'bench_write_req.py' allows comparing performances of write
request for two qemu-img binary files.
An example with (qemu-img binary 1) and without (qemu-img binary 2) the
applied patch "qcow2: skip writing zero buffers to empty COW areas"
(git commit ID: c8bb23cbdbe32f5) has the following results:

SSD:
-  ---  ---
 
  0.34 +- 0.01 10.57 +- 0.96
 0.33 +- 0.01 9.15 +- 0.85
   0.33 +- 0.00 8.72 +- 0.05
  7.43 +- 1.19 14.35 +- 1.00
-  ---  ---
HDD:
-  ---  ---
 
  32.61 +- 1.1755.11 +- 1.15
 54.28 +- 8.8260.11 +- 2.76
   57.93 +- 0.4758.53 +- 0.51
  11.47 +- 0.9417.29 +- 4.40
-  ---  ---

Suggested-by: Denis V. Lunev 
Suggested-by: Vladimir Sementsov-Ogievskiy 
Signed-off-by: Andrey Shinkevich 
---
 scripts/simplebench/bench_write_req.py | 173 +
 1 file changed, 173 insertions(+)
 create mode 100755 scripts/simplebench/bench_write_req.py

diff --git a/scripts/simplebench/bench_write_req.py 
b/scripts/simplebench/bench_write_req.py
new file mode 100755
index 000..a285ef1
--- /dev/null
+++ b/scripts/simplebench/bench_write_req.py
@@ -0,0 +1,173 @@
+#!/usr/bin/env python3
+#
+# Test to compare performance of write requests for two qemu-img binary files.
+#
+# Copyright (c) 2020 Virtuozzo International GmbH.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see .
+#
+
+
+import sys
+import os
+import subprocess
+import simplebench
+
+
+def bench_func(env, case):
+""" Handle one "cell" of benchmarking table. """
+return bench_write_req(env['qemu_img'], env['image_name'],
+   case['block_size'], case['block_offset'],
+   case['requests'])
+
+
+def qemu_img_pipe(*args):
+'''Run qemu-img and return its output'''
+subp = subprocess.Popen(list(args),
+stdout=subprocess.PIPE,
+stderr=subprocess.STDOUT,
+universal_newlines=True)
+exitcode = subp.wait()
+if exitcode < 0:
+sys.stderr.write('qemu-img received signal %i: %s\n'
+ % (-exitcode, ' '.join(list(args
+return subp.communicate()[0]
+
+
+def bench_write_req(qemu_img, image_name, block_size, block_offset, requests):
+"""Benchmark write requests
+
+The function creates a QCOW2 image with the given path/name and fills it
+with random data optionally. Then it runs the 'qemu-img bench' command and
+makes series of write requests on the image clusters. Finally, it returns
+the total time of the write operations on the disk.
+
+qemu_img -- path to qemu_img executable file
+image_name   -- QCOW2 image name to create
+block_size   -- size of a block to write to clusters
+block_offset -- offset of the block in clusters
+requests -- number of write requests per cluster
+
+Returns {'seconds': int} on success and {'error': str} on failure.
+Return value is compatible with simplebench lib.
+"""
+
+if not os.path.isfile(qemu_img):
+print(f'File not found: {qemu_img}')
+sys.exit(1)
+
+image_dir = os.path.dirname(os.path.abspath(image_name))
+if not os.path.isdir(image_dir):
+print(f'Path not found: {image_name}')
+sys.exit(1)
+
+cluster_size = 1024 * 1024
+image_size = 1024 * cluster_size
+seek = 4
+dd_count = int(image_size / cluster_size) - seek
+
+args_create = [qemu_img, 'create', '-f', 'qcow2', '-o',
+   f'cluster_size={cluster_size}',
+   image_name, str(image_size)]
+
+count = requests * int(image_size / cluster_size)
+step = str(cluster_size)
+offset = str(block_offset)
+cnt = str(count)
+size = []
+if block_size:
+size = ['-s', f'{block_size}']
+
+args_bench = [qemu_img, 'bench', '-w', '-n', '-t', 'none', '-c', cnt,
+  '-S', step, '-o', offset, '-f', 'qcow2', image_name]
+if block_size:
+args_bench.extend(size)
+
+try:
+qemu_img_pipe(*args_create)
+except OSError as e:
+os.remove(image_name)
+return