Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Speedup: use a C struct for the blkparse parsing.

  • Loading branch information...
commit 0cfc3e7dd70ad1fc2bd241d41db548c47080645b 1 parent 1411a5e
@chrismason-xx chrismason-xx authored
View
5 README.html
@@ -4,6 +4,11 @@
patterns and performance. It can plot multiple blktrace runs together,
making it easy to compare the differences between different benchmark runs.</p>
+<h3>Installing:</h3>
+
+<p>seekwatcher depends on python, cython and matplotlib. These are available
+from most distros. Once you have installed them, use python setup.py install</p>
+
<h3>Examples:</h3>
<a href=http://oss.oracle.com/~mason/seekwatcher/ext3.compilebench.20.png>Ext3 creating 20 copies of the Linux kernel sources</a><p>
View
29 cmd/seekwatcher
@@ -608,7 +608,8 @@ def run_blkparse(trace):
for x in tracefiles:
print "using tracefile %s" % os.path.join(trace_dir, x)
fh = tempfile.NamedTemporaryFile(dir=".")
- os.system('blkparse -q -D ' + trace_dir + ' -i ' + x + ' -d ' + fh.name + ' -O >& /dev/null')
+ os.system('blkparse -q -D ' + trace_dir + ' -i ' + x +
+ ' -d ' + fh.name + ' -O >& /dev/null')
loaddata(fh, rd)
return rd
@@ -677,23 +678,6 @@ def translate_sector(dev, sector):
return device_translate[dev] + sector;
-def process_input(input, type):
- global devices_sector_max
- global device_translate
- global must_sort
-
- if type == 0:
- run = run_blkparse(input)
- elif type == 1:
- if input == "-":
- p = sys.stdin
- else:
- p = open(input, 'r')
- run = rundata.rundata()
- loaddata(p, run)
-
- return run
-
# find either the highest or lowest value in stats
# for a given column and change that cell in the table
# read. To find the highest use find_max = True, lowest
@@ -764,8 +748,6 @@ parser.add_option("-D", "--blktrace-destination",
help="Destination for blktrace", default=".")
parser.add_option("-t", "--trace", help="blktrace file", default=[],
action="append")
-parser.add_option("-f", "--file", help="parsed blktrace file", default=[],
- action="append")
parser.add_option("-p", "--prog", help="exec program", default="")
parser.add_option("", "--full-trace", help="Don't filter blktrace events",
default=False, action="store_true")
@@ -897,7 +879,6 @@ if options.prog:
options.title = options.prog
graphs = [ [1, 'io'], [2, 'tput'], [3, 'seek'], [4, 'iops'], [5, 'stats'] ]
-#graphs = [ [1, 'io'], [2, 'tput'], [3, 'seek'], [5, 'stats'] ]
# fix up our array of which graphs to print
if options.only_graph:
@@ -948,11 +929,7 @@ devices_sector_max = {}
device_translate = {}
for x in options.trace:
- run = process_input(x, 0)
- runs.append(run)
-
-for x in options.file:
- run = process_input(x, 1)
+ run = run_blkparse(x)
runs.append(run)
# if our traces included more than one device,
View
90 seekwatcher/blkparse.pyx
@@ -1,20 +1,27 @@
import numpy
import struct
+import os
cimport numpy
-
-#struct blk_io_trace {
-# 0 __u32 magic; /* MAGIC << 8 | version */
-# 1 __u32 sequence; /* event number */
-# 2 __u64 time; /* in nanoseconds */
-# 3 __u64 sector; /* disk offset */
-# 4 __u32 bytes; /* transfer length */
-# 5 __u32 action; /* what happened */
-# 6 __u32 pid; /* who did it */
-# 7 __u32 device; /* device identifier (dev_t) */
-# 8 __u32 cpu; /* on what cpu did it happen */
-# 9 __u16 error; /* completion error */
-# 10 __u16 pdu_len; /* length of data after this trace */
-#};
+cdef extern from "unistd.h":
+ int read(int fd, void *buf, int count)
+
+cdef extern from "inttypes.h":
+ ctypedef int uint32_t
+ ctypedef int uint64_t
+ ctypedef int uint16_t
+
+cdef struct blk_io_trace:
+ uint32_t magic # /* MAGIC << 8 | version */
+ uint32_t sequence # /* event number */
+ uint64_t time # /* in nanoseconds */
+ uint64_t sector # /* disk offset */
+ uint32_t bytes # /* transfer length */
+ uint32_t action # /* what happened */
+ uint32_t pid # /* who did it */
+ uint32_t device # /* device identifier (dev_t) */
+ uint32_t cpu # /* on what cpu did it happen */
+ uint16_t error # /* completion error */
+ uint16_t pdu_len # /* length of data after this trace */
cdef int BLK_TC_SHIFT = 16
cdef unsigned int BLK_TC_ACT(unsigned int act):
@@ -112,6 +119,16 @@ cdef float dev_to_float(unsigned major, unsigned minor):
return res + float(major)
+cdef skip_bytes(int fd, int num_bytes, char *buf, int buf_size):
+ cdef int val
+ cdef int ret
+ while num_bytes > 0:
+ val = min(num_bytes, buf_size)
+ ret = read(fd, buf, val)
+ if ret < 0:
+ return
+ num_bytes -= ret
+
def read_events(fp, numpy.ndarray[numpy.float_t, ndim=1] row, tags, pid_map):
cdef int ret = 0
cdef unsigned action
@@ -122,46 +139,50 @@ def read_events(fp, numpy.ndarray[numpy.float_t, ndim=1] row, tags, pid_map):
cdef int rw
cdef unsigned major
cdef unsigned minor
+ cdef char buf[4096]
+ cdef int fd = fp.fileno()
+ cdef int num
+ cdef blk_io_trace *trace
while True:
- record = fp.read(format_size)
- if not record:
+
+ num = read(fd, buf, format_size)
+ if num < format_size:
break
- c = struct.unpack(format, record)
- action = c[5]
+ trace = <blk_io_trace *>buf
+ action = trace.action
+
if action == BLK_TN_PROCESS and tags:
- payload_size = c[10]
- payload = fp.read(payload_size)
+ payload_size = trace.pdu_len
+ payload = os.read(fd, payload_size)
idx = payload.find('\0')
if idx >= 0:
payload = payload[:idx]
- pid_map[c[6]] = payload
+ pid_map[trace.pid] = payload
continue
act = action & 0xffff
- size = c[4]
+ size = trace.bytes
if (size == 0 or (act != __BLK_TA_COMPLETE and
act != __BLK_TA_QUEUE and
act != __BLK_TA_ISSUE)):
- skip = c[10]
- if skip:
- fp.read(skip)
+ skip_bytes(fd, trace.pdu_len, buf, 4096)
continue
- time = float(c[2]) / 1000000000.0
+ time = float(trace.time) / 1000000000.0
rw = action & BLK_TC_ACT(BLK_TC_WRITE) != 0
- major = MAJOR(c[7])
- minor = MINOR(c[7])
+ major = MAJOR(trace.device)
+ minor = MINOR(trace.device)
ret = 1
row[1] = rw
row[2] = major
row[3] = minor
- row[4] = c[3]
+ row[4] = trace.sector
row[5] = size
- row[6] = c[1]
+ row[6] = trace.sequence
row[7] = time
row[8] = dev_to_float(major, minor)
row[9] = 0
@@ -169,14 +190,13 @@ def read_events(fp, numpy.ndarray[numpy.float_t, ndim=1] row, tags, pid_map):
if act == __BLK_TA_QUEUE and size > 0:
row[0] = 0.0
if tags:
- tags[0] = c[6]
- tags[1] = pid_map.get(c[6], "none")
+ tags[0] = trace.pid
+ tags[1] = pid_map.get(trace.pid, "none")
elif act == __BLK_TA_COMPLETE and size > 0:
row[0] = 1.0
elif act == __BLK_TA_ISSUE and size > 0:
row[0] = 4.0
- skip = c[10]
- if skip:
- fp.read(skip)
+
+ skip_bytes(fd, trace.pdu_len, buf, 4096)
break
return ret
View
2  seekwatcher/rundata.pyx
@@ -269,7 +269,7 @@ cdef class rundata:
if (this_op == last_op and
this_rw == last_rw and
this_dev == last_dev and
- this_time - last_time < .5 and last_size < 1024 and
+ this_time - last_time < .5 and last_size < 512 and
this_sector == last_end and this_tag == last_tag):
last_end += this_size
last_size += this_size
Please sign in to comment.
Something went wrong with that request. Please try again.