Skip to content

Commit 21cf00b

Browse files
committed
testWrite.py - Make OS-independent (aka support running test on windows), and add usage info and validation.
Changes: * Generate a file the size of my current libc instead of relying on finding one via linux-only path * Navigate to current directory of testWrite.py and use relative paths to test filenames, instead of writing in /home/${USERNAME}/ (now supports windows and non-standard $HOME locations) * Add --help usage info * Perform validation on arguments, including number of arguments and validity of the priorities provided * Minor cleanups and improvements
1 parent 3f011b3 commit 21cf00b

1 file changed

Lines changed: 122 additions & 26 deletions

File tree

testWrite.py

Lines changed: 122 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/usr/bin/env python
22
'''
3-
This testWrite.py file is a testcase for python-nonblock (c) 2015,2016,2017 Tim Savannah.
3+
This testWrite.py file is a testcase for python-nonblock Copyright (c) 2015, 2016, 2017, 2019 Timothy Savannah.
44
55
The testcase itself is hereby granted access as a Public Domain work, or the closest legally in your area.
66
@@ -22,11 +22,13 @@
2222
and off. For example, if you are running a dd if=/dev/urandom of=testfile bs=512 to simulate background I/O on the same device,
2323
it will flush both datasets. This is moreso intended to be set to True when NO background I/O is going.
2424
'''
25+
2526
import os
26-
import glob
2727
import time
2828
import sys
2929
import subprocess
30+
import tempfile
31+
3032
from nonblock import bgwrite, bgwrite_chunk
3133

3234

@@ -37,55 +39,142 @@ class dummy(object):
3739
pass
3840

3941

40-
# Pick a big file
42+
# TODO: Use os.linesep instead of explicit '\n' ?
43+
44+
# Generate a big file
4145

4246
# Set to True to sync ALL I/O (this process and others) to disk before each test.
4347
# This should be True if no background I/O is being ran, and maybe True maybe False if some is running.
4448
# It will make tests more "fair" between eachother, but with various background tasks it may introduce
4549
# a large variance and margin of error.
4650
DO_SYNC = True
4751

52+
def printUsage():
53+
sys.stderr.write('''Usage: %s (Optional: [start prio] [end prio])
54+
Runs through priority levels, either specified start/end (inclusive), or if no args provided, the full set 1-9.
55+
56+
If specified, start prio must be <= end prio,
57+
start prio must be >= 1,
58+
end prio must be <= 9.
59+
60+
Tests interactivity by performing math during two sets of simultaneous bgwrites
61+
''' %(os.path.basename(__file__), )
62+
)
63+
sys.stderr.flush()
64+
4865
if __name__ == '__main__':
4966

50-
BIG_FILE = glob.glob('/usr/lib/libc-2.*.so')[0]
67+
if '--help' in sys.argv:
68+
printUsage()
69+
sys.exit(0)
5170

52-
startPrio = 1
53-
endPrio = 10
71+
if len(sys.argv) not in (1, 3):
72+
sys.stderr.write('Invalid arguments.\n\n')
73+
printUsage()
74+
sys.exit(1)
5475

5576
if len(sys.argv) == 3:
77+
## They have provided a start and end priority
78+
79+
# Validate they are integers
80+
if not sys.argv[1].isdigit() and not sys.argv[2].isdigit():
81+
sys.stderr.write('Right number of arguments, but not whole integers.\n\n')
82+
printUsage()
83+
sys.exit(1)
84+
85+
# Extract priorities to test from arguments
5686
startPrio = int(sys.argv[1])
57-
endPrio = int(sys.argv[2]) + 1
87+
endPrio = int(sys.argv[2])
88+
89+
# Validate these are valid priorities, and in valid order
90+
if startPrio > endPrio:
91+
sys.stderr.write('Start priority is greater than end priority, impossible!\n\n')
92+
printUsage()
93+
sys.exit(1)
94+
95+
if startPrio < 1:
96+
sys.stderr.write('Start priority must be >= 1\n\n')
97+
printUsage()
98+
sys.exit(1)
99+
100+
if endPrio > 9:
101+
sys.stderr.write('End priority must be <= 9\n\n')
102+
printUsage()
103+
sys.exit(1)
104+
105+
else:
106+
107+
print ( 'No arguments provided, defaulting to testing full set (1-9 inclusive) of IO priorities\n' )
108+
109+
startPrio = 1
110+
endPrio = 9
111+
112+
113+
114+
## Generate a fairly large dataset
115+
116+
bigFile = tempfile.NamedTemporaryFile(mode='wt')
117+
# Write some data
118+
numLetters = ord('z') - ord('a')
119+
lettersLst = [ chr( ord('a') + i ) for i in range(numLetters) ]
120+
lettersStr = ''.join(lettersLst)
121+
curLen = 0
122+
before = time.time()
123+
# Size of my libc at time of writing
124+
while curLen < 2317344:
125+
bigFile.write(lettersStr)
126+
curLen += numLetters
127+
128+
# Try to force flush
129+
try:
130+
bigFile.flush()
131+
except:
132+
pass
133+
after = time.time()
134+
135+
print ( 'Generated %d bytes of data in %.5f seconds.' %( curLen, after - before ) )
136+
137+
bigFilename = bigFile.name
138+
139+
currentDirectory = os.path.abspath( os.path.dirname( __file__ ) )
140+
baseFilename = os.path.basename( __file__ )
141+
print ( 'Using containing directory of this file [ %s ] for writes...\n' %( currentDirectory, ) )
142+
143+
# Change dir to this directory, so we don't have to use os.sep
144+
os.chdir(currentDirectory)
58145

59146
username = os.environ['USER']
60147

61148
# Some values used for the math
62149
x = 13
63150
y = 37
64-
65-
# Get some big data
66-
with open(BIG_FILE, 'rb') as f:
151+
152+
# Get some big data - open a fresh copy so we aren't reading from buffer
153+
with open(bigFilename, 'rb') as f:
67154
before = time.time()
68155
data = f.read()
69156
after = time.time()
70157

71-
sys.stdout.write('Time to read: %f\n' %(after - before,))
158+
print ('Time to read %d bytes: %f\n' %(len(data), after - before,) )
159+
160+
print ( 'Running through IO priorities, %d -> %d (inclusive),\n whilst running simultaneous math calculations to test interactivity\n and I/O rate at each level...\n\n%s\n\n' %( startPrio, endPrio, '-' * 50, ) )
72161

73162
# Expand that big data
74163
data = data * 50
75164

76165
dataLen = len(data)
77166

78167
# Iterate through the I/O priorities, do the operation, and show the score.
79-
for ioPrio in range(startPrio, endPrio, 1):
168+
for ioPrio in range(startPrio, endPrio + 1, 1):
80169
answers = [22]
81170
answers2 = [16]
82171
answers3 = [81]
83-
if os.path.exists('/home/%s/nb_test_output1' %(username,)):
84-
os.unlink('/home/%s/nb_test_output1' %(username,))
85-
if os.path.exists('/home/%s/nb_test_output2' %(username,)):
86-
os.unlink('/home/%s/nb_test_output2' %(username,))
87-
f = open('/home/%s/nb_test_output1' %(username,), 'wb')
88-
f2 = open('/home/%s/nb_test_output2' %(username,), 'wb')
172+
if os.path.exists('nb_test_output1'):
173+
os.unlink('nb_test_output1')
174+
if os.path.exists('nb_test_output2'):
175+
os.unlink('nb_test_output2')
176+
f = open('nb_test_output1', 'wb')
177+
f2 = open('nb_test_output2', 'wb')
89178

90179
if DO_SYNC is True:
91180
# Ensure pending data is flushed so next run has fair chance
@@ -131,17 +220,24 @@ class dummy(object):
131220
numAnswers = len(answers) + len(answers2) + len(answers3) - 3
132221
delta = round(after - before, 5)
133222

134-
sys.stdout.write(('-' * 40) + '\n')
135-
sys.stdout.write('[%d] Time to write: %f\n' %(ioPrio, delta) )
136-
sys.stdout.write('[%d] Number of answers generated: %d\n' %(ioPrio, numAnswers) )
223+
sys.stdout.write(('-' * 50) + '\n')
224+
sys.stdout.write('[%d] Time to write: %f seconds\n' %(ioPrio, delta) )
225+
sys.stdout.write('[%d] Number of answers generated during writes: %d\n' %(ioPrio, numAnswers) )
137226
sys.stdout.write('[%d] Average write speed: %f M/s\n' %(ioPrio, round((dataLen / delta) / (1024.0 * 1024.0), 5) ) )
138227
sys.stdout.write('[%d] Interactivity score: %f\n' % (ioPrio, round(numAnswers / delta, 5)) )
139-
sys.stdout.write(('=' * 40) + '\n\n')
228+
sys.stdout.write(('=' * 50) + '\n\n')
140229
sys.stdout.flush()
141230

142231

143232

144-
if os.path.exists('/home/%s/nb_test_output1' %(username,)):
145-
os.unlink('/home/%s/nb_test_output1' %(username,))
146-
if os.path.exists('/home/%s/nb_test_output2' %(username,)):
147-
os.unlink('/home/%s/nb_test_output2' %(username,))
233+
print ( 'Cleaning-up')
234+
235+
if os.path.exists('nb_test_output1'):
236+
os.unlink('nb_test_output1')
237+
if os.path.exists('nb_test_output2'):
238+
os.unlink('nb_test_output2')
239+
240+
# Cleanup the generated data
241+
bigFile.close()
242+
243+
# vim: set ts=4 st=4 sw=4 expandtab :

0 commit comments

Comments
 (0)