| 1 |
#!/usr/bin/python2.4 |
| 2 |
# xdelta 3 - delta compression tools and library |
| 3 |
# Copyright (C) 2003, 2006, 2007. Joshua P. MacDonald |
| 4 |
# |
| 5 |
# This program is free software; you can redistribute it and/or modify |
| 6 |
# it under the terms of the GNU General Public License as published by |
| 7 |
# the Free Software Foundation; either version 2 of the License, or |
| 8 |
# (at your option) any later version. |
| 9 |
# |
| 10 |
# This program is distributed in the hope that it will be useful, |
| 11 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 12 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 13 |
# GNU General Public License for more details. |
| 14 |
# |
| 15 |
# You should have received a copy of the GNU General Public License |
| 16 |
# along with this program; if not, write to the Free Software |
| 17 |
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| 18 |
|
| 19 |
# TODO: test 1.5 vs. greedy |
| 20 |
|
| 21 |
import os, sys, math, re, time, types, array, random |
| 22 |
import xdelta3main |
| 23 |
import xdelta3 |
| 24 |
|
| 25 |
#RCSDIR = '/mnt/polaroid/Polaroid/orbit_linux/home/jmacd/PRCS' |
| 26 |
RCSDIR = '/tmp/PRCS_read_copy' |
| 27 |
SAMPLEDIR = "/tmp/WESNOTH_tmp/diff" |
| 28 |
|
| 29 |
#RCSDIR = 'G:/jmacd/PRCS/prcs/b' |
| 30 |
#SAMPLEDIR = "C:/sample_data/Wesnoth/tar" |
| 31 |
|
| 32 |
# |
| 33 |
MIN_SIZE = 0 |
| 34 |
|
| 35 |
TIME_TOO_SHORT = 0.050 |
| 36 |
|
| 37 |
SKIP_TRIALS = 2 |
| 38 |
MIN_TRIALS = 3 |
| 39 |
MAX_TRIALS = 15 |
| 40 |
|
| 41 |
SKIP_DECODE = 1 |
| 42 |
|
| 43 |
# 10 = fast 1.5 = slow |
| 44 |
MIN_STDDEV_PCT = 1.5 |
| 45 |
|
| 46 |
# How many results per round |
| 47 |
MAX_RESULTS = 500 |
| 48 |
TEST_ROUNDS = 500 |
| 49 |
KEEP_P = (0.5) |
| 50 |
|
| 51 |
# For RCS testing, what percent to select |
| 52 |
FILE_P = (0.30) |
| 53 |
|
| 54 |
# For run-speed tests |
| 55 |
MIN_RUN = 1000 * 1000 * 1 |
| 56 |
MAX_RUN = 1000 * 1000 * 10 |
| 57 |
|
| 58 |
# Testwide defaults |
| 59 |
ALL_ARGS = [ |
| 60 |
# -v |
| 61 |
] |
| 62 |
|
| 63 |
# The first 7 args go to -C |
| 64 |
SOFT_CONFIG_CNT = 7 |
| 65 |
|
| 66 |
CONFIG_ORDER = [ 'large_look', |
| 67 |
'large_step', |
| 68 |
'small_look', |
| 69 |
'small_chain', |
| 70 |
'small_lchain', |
| 71 |
'max_lazy', |
| 72 |
'long_enough', |
| 73 |
|
| 74 |
# > SOFT_CONFIG_CNT |
| 75 |
'nocompress', |
| 76 |
'winsize', |
| 77 |
'srcwinsize', |
| 78 |
'sprevsz', |
| 79 |
'iopt', |
| 80 |
'djw', |
| 81 |
'altcode', |
| 82 |
] |
| 83 |
|
| 84 |
CONFIG_ARGMAP = { |
| 85 |
'winsize' : '-W', |
| 86 |
'srcwinsize' : '-B', |
| 87 |
'sprevsz' : '-P', |
| 88 |
'iopt' : '-I', |
| 89 |
'nocompress' : '-N', |
| 90 |
'djw' : '-Sdjw', |
| 91 |
'altcode' : '-T', |
| 92 |
} |
| 93 |
|
| 94 |
def INPUT_SPEC(rand): |
| 95 |
return { |
| 96 |
|
| 97 |
# Time/space costs: |
| 98 |
|
| 99 |
# -C 1,2,3,4,5,6,7 |
| 100 |
'large_look' : lambda d: rand.choice([9]), |
| 101 |
'large_step' : lambda d: rand.choice([3, 5, 7, 8, 15]), |
| 102 |
'small_chain' : lambda d: rand.choice([40, 10, 4, 1]), |
| 103 |
'small_lchain' : lambda d: rand.choice([x for x in [10, 4, 2, 1] if x <= d['small_chain']]), |
| 104 |
'max_lazy' : lambda d: rand.choice([9, 18, 27, 36, 72, 108]), |
| 105 |
'long_enough' : lambda d: rand.choice([9, 18, 27, 36, 72, 108]), |
| 106 |
'small_look' : lambda d: rand.choice([4]), |
| 107 |
|
| 108 |
# -N |
| 109 |
'nocompress' : lambda d: rand.choice(['true']), |
| 110 |
|
| 111 |
# -T |
| 112 |
'altcode' : lambda d: rand.choice(['false']), |
| 113 |
|
| 114 |
# -S djw |
| 115 |
'djw' : lambda d: rand.choice(['false']), |
| 116 |
|
| 117 |
# Memory costs: |
| 118 |
|
| 119 |
# -W |
| 120 |
'winsize' : lambda d: 8 * (1<<20), |
| 121 |
|
| 122 |
# -B |
| 123 |
'srcwinsize' : lambda d: 64 * (1<<20), |
| 124 |
|
| 125 |
# -I 0 is unlimited |
| 126 |
'iopt' : lambda d: 0, |
| 127 |
|
| 128 |
# -P only powers of two |
| 129 |
'sprevsz' : lambda d: rand.choice([x * (1<<16) for x in [4]]), |
| 130 |
} |
| 131 |
#end |
| 132 |
|
| 133 |
# |
| 134 |
TMPDIR = '/tmp/xd3regtest.%d' % os.getpid() |
| 135 |
|
| 136 |
RUNFILE = os.path.join(TMPDIR, 'run') |
| 137 |
DFILE = os.path.join(TMPDIR, 'output') |
| 138 |
RFILE = os.path.join(TMPDIR, 'recon') |
| 139 |
|
| 140 |
HEAD_STATE = 0 |
| 141 |
BAR_STATE = 1 |
| 142 |
REV_STATE = 2 |
| 143 |
DATE_STATE = 3 |
| 144 |
|
| 145 |
# |
| 146 |
IGNORE_FILENAME = re.compile('.*\\.(gif|jpg).*') |
| 147 |
|
| 148 |
# rcs output |
| 149 |
RE_TOTREV = re.compile('total revisions: (\\d+)') |
| 150 |
RE_BAR = re.compile('----------------------------') |
| 151 |
RE_REV = re.compile('revision (.+)') |
| 152 |
RE_DATE = re.compile('date: ([^;]+);.*') |
| 153 |
# xdelta output |
| 154 |
RE_HDRSZ = re.compile('VCDIFF header size: +(\\d+)') |
| 155 |
RE_EXTCOMP = re.compile('XDELTA ext comp.*') |
| 156 |
|
| 157 |
def c2str(c): |
| 158 |
return ' '.join(['%s' % x for x in c]) |
| 159 |
#end |
| 160 |
|
| 161 |
def SumList(l): |
| 162 |
return reduce(lambda x,y: x+y, l) |
| 163 |
#end |
| 164 |
|
| 165 |
# returns (total, mean, stddev, q2 (median), |
| 166 |
# (q3-q1)/2 ("semi-interquartile range"), max-min (spread)) |
| 167 |
class StatList: |
| 168 |
def __init__(self,l,desc): |
| 169 |
cnt = len(l) |
| 170 |
assert(cnt > 1) |
| 171 |
l.sort() |
| 172 |
self.cnt = cnt |
| 173 |
self.l = l |
| 174 |
self.total = SumList(l) |
| 175 |
self.mean = self.total / float(self.cnt) |
| 176 |
self.s = math.sqrt(SumList([(x-self.mean) * (x - self.mean) for x in l]) / float(self.cnt-1)) |
| 177 |
self.q0 = l[0] |
| 178 |
self.q1 = l[int(self.cnt/4.0+0.5)] |
| 179 |
self.q2 = l[int(self.cnt/2.0+0.5)] |
| 180 |
self.q3 = l[min(self.cnt-1,int((3.0*self.cnt)/4.0+0.5))] |
| 181 |
self.q4 = l[self.cnt-1]+1 |
| 182 |
self.siqr = (self.q3-self.q1)/2.0; |
| 183 |
self.spread = (self.q4-self.q0) |
| 184 |
self.str = '%s %d; mean %d; sdev %d; q2 %d; .5(q3-q1) %.1f; spread %d' % \ |
| 185 |
(desc, self.total, self.mean, self.s, self.q2, self.siqr, self.spread) |
| 186 |
#end |
| 187 |
#end |
| 188 |
|
| 189 |
def RunCommand(args, ok = [0]): |
| 190 |
#print 'run command %s' % (' '.join(args)) |
| 191 |
p = os.spawnvp(os.P_WAIT, args[0], args) |
| 192 |
if p not in ok: |
| 193 |
raise CommandError(args, 'exited %d' % p) |
| 194 |
#end |
| 195 |
#end |
| 196 |
|
| 197 |
def RunCommandIO(args,infn,outfn): |
| 198 |
p = os.fork() |
| 199 |
if p == 0: |
| 200 |
os.dup2(os.open(infn,os.O_RDONLY),0) |
| 201 |
os.dup2(os.open(outfn,os.O_CREAT|os.O_TRUNC|os.O_WRONLY),1) |
| 202 |
os.execvp(args[0], args) |
| 203 |
else: |
| 204 |
s = os.waitpid(p,0) |
| 205 |
o = os.WEXITSTATUS(s[1]) |
| 206 |
if not os.WIFEXITED(s[1]) or o != 0: |
| 207 |
raise CommandError(args, 'exited %d' % o) |
| 208 |
#end |
| 209 |
#end |
| 210 |
#end |
| 211 |
|
| 212 |
class TimedTest: |
| 213 |
def __init__(self, target, source, runnable, |
| 214 |
skip_trials = SKIP_TRIALS, |
| 215 |
min_trials = MIN_TRIALS, |
| 216 |
max_trials = MAX_TRIALS, |
| 217 |
min_stddev_pct = MIN_STDDEV_PCT): |
| 218 |
self.target = target |
| 219 |
self.source = source |
| 220 |
self.runnable = runnable |
| 221 |
|
| 222 |
self.skip_trials = skip_trials |
| 223 |
self.min_trials = min(min_trials, max_trials) |
| 224 |
self.max_trials = max_trials |
| 225 |
self.min_stddev_pct = min_stddev_pct |
| 226 |
|
| 227 |
self.encode_time = self.DoTest(DFILE, |
| 228 |
lambda x: x.Encode(self.target, self.source, DFILE)) |
| 229 |
self.encode_size = runnable.EncodeSize(DFILE) |
| 230 |
|
| 231 |
if SKIP_DECODE: |
| 232 |
self.decode_time = StatList([1, 1], 'not decoded') |
| 233 |
return |
| 234 |
#end |
| 235 |
|
| 236 |
self.decode_time = self.DoTest(RFILE, |
| 237 |
lambda x: x.Decode(DFILE, self.source, RFILE), |
| 238 |
) |
| 239 |
|
| 240 |
# verify |
| 241 |
runnable.Verify(self.target, RFILE) |
| 242 |
#end |
| 243 |
|
| 244 |
def DoTest(self, fname, func): |
| 245 |
trials = 0 |
| 246 |
measured = [] |
| 247 |
|
| 248 |
while 1: |
| 249 |
try: |
| 250 |
os.remove(fname) |
| 251 |
except OSError: |
| 252 |
pass |
| 253 |
|
| 254 |
start_time = time.time() |
| 255 |
start_clock = time.clock() |
| 256 |
|
| 257 |
func(self.runnable) |
| 258 |
|
| 259 |
total_clock = (time.clock() - start_clock) |
| 260 |
total_time = (time.time() - start_time) |
| 261 |
|
| 262 |
elap_time = max(total_time, 0.0000001) |
| 263 |
elap_clock = max(total_clock, 0.0000001) |
| 264 |
|
| 265 |
trials = trials + 1 |
| 266 |
|
| 267 |
# skip some of the first trials |
| 268 |
if trials > self.skip_trials: |
| 269 |
measured.append((elap_clock, elap_time)) |
| 270 |
#print 'measurement total: %.1f ms' % (total_time * 1000.0) |
| 271 |
|
| 272 |
# at least so many |
| 273 |
if trials < (self.skip_trials + self.min_trials): |
| 274 |
#print 'continue: need more trials: %d' % trials |
| 275 |
continue |
| 276 |
|
| 277 |
# compute %variance |
| 278 |
done = 0 |
| 279 |
if self.skip_trials + self.min_trials <= 2: |
| 280 |
measured = measured + measured; |
| 281 |
done = 1 |
| 282 |
#end |
| 283 |
|
| 284 |
time_stat = StatList([x[1] for x in measured], 'elap time') |
| 285 |
sp = float(time_stat.s) / float(time_stat.mean) |
| 286 |
|
| 287 |
# what if MAX_TRIALS is exceeded? |
| 288 |
too_many = (trials - self.skip_trials) >= self.max_trials |
| 289 |
good = (100.0 * sp) < self.min_stddev_pct |
| 290 |
if done or too_many or good: |
| 291 |
trials = trials - self.skip_trials |
| 292 |
if not done and not good: |
| 293 |
#print 'too many trials: %d' % trials |
| 294 |
pass |
| 295 |
#clock = StatList([x[0] for x in measured], 'elap clock') |
| 296 |
return time_stat |
| 297 |
#end |
| 298 |
#end |
| 299 |
#end |
| 300 |
#end |
| 301 |
|
| 302 |
def Decimals(start, end): |
| 303 |
l = [] |
| 304 |
step = start |
| 305 |
while 1: |
| 306 |
r = range(step, step * 10, step) |
| 307 |
l = l + r |
| 308 |
if step * 10 >= end: |
| 309 |
l.append(step * 10) |
| 310 |
break |
| 311 |
step = step * 10 |
| 312 |
return l |
| 313 |
#end |
| 314 |
|
| 315 |
# This tests the raw speed of 0-byte inputs |
| 316 |
def RunSpeedTest(): |
| 317 |
for L in Decimals(MIN_RUN, MAX_RUN): |
| 318 |
SetFileSize(RUNFILE, L) |
| 319 |
|
| 320 |
trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<20)])) |
| 321 |
ReportSpeed(L, trx, '1MB ') |
| 322 |
|
| 323 |
trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<19)])) |
| 324 |
ReportSpeed(L, trx, '512k') |
| 325 |
|
| 326 |
trx = TimedTest(RUNFILE, None, Xdelta3Runner(['-W', str(1<<18)])) |
| 327 |
ReportSpeed(L, trx, '256k') |
| 328 |
|
| 329 |
trm = TimedTest(RUNFILE, None, Xdelta3Mod1(RUNFILE)) |
| 330 |
ReportSpeed(L, trm, 'swig') |
| 331 |
|
| 332 |
trg = TimedTest(RUNFILE, None, GzipRun1()) |
| 333 |
ReportSpeed(L,trg,'gzip') |
| 334 |
#end |
| 335 |
#end |
| 336 |
|
| 337 |
def SetFileSize(F,L): |
| 338 |
fd = os.open(F, os.O_CREAT | os.O_WRONLY) |
| 339 |
os.ftruncate(fd,L) |
| 340 |
assert os.fstat(fd).st_size == L |
| 341 |
os.close(fd) |
| 342 |
#end |
| 343 |
|
| 344 |
def ReportSpeed(L,tr,desc): |
| 345 |
print '%s run length %u: size %u: time %.3f ms: decode %.3f ms' % \ |
| 346 |
(desc, L, |
| 347 |
tr.encode_size, |
| 348 |
tr.encode_time.mean * 1000.0, |
| 349 |
tr.decode_time.mean * 1000.0) |
| 350 |
#end |
| 351 |
|
| 352 |
class Xdelta3RunClass: |
| 353 |
def __init__(self, extra): |
| 354 |
self.extra = extra |
| 355 |
#end |
| 356 |
|
| 357 |
def __str__(self): |
| 358 |
return ' '.join(self.extra) |
| 359 |
#end |
| 360 |
|
| 361 |
def New(self): |
| 362 |
return Xdelta3Runner(self.extra) |
| 363 |
#end |
| 364 |
#end |
| 365 |
|
| 366 |
class Xdelta3Runner: |
| 367 |
def __init__(self, extra): |
| 368 |
self.extra = extra |
| 369 |
#end |
| 370 |
|
| 371 |
def Encode(self, target, source, output): |
| 372 |
args = (ALL_ARGS + |
| 373 |
self.extra + |
| 374 |
['-e']) |
| 375 |
if source: |
| 376 |
args.append('-s') |
| 377 |
args.append(source) |
| 378 |
#end |
| 379 |
args = args + [target, output] |
| 380 |
self.Main(args) |
| 381 |
#end |
| 382 |
|
| 383 |
def Decode(self, input, source, output): |
| 384 |
args = (ALL_ARGS + |
| 385 |
['-d']) |
| 386 |
if source: |
| 387 |
args.append('-s') |
| 388 |
args.append(source) |
| 389 |
#end |
| 390 |
args = args + [input, output] |
| 391 |
self.Main(args) |
| 392 |
#end |
| 393 |
|
| 394 |
def Verify(self, target, recon): |
| 395 |
RunCommand(('cmp', target, recon)) |
| 396 |
#end |
| 397 |
|
| 398 |
def EncodeSize(self, output): |
| 399 |
return os.stat(output).st_size |
| 400 |
#end |
| 401 |
|
| 402 |
def Main(self, args): |
| 403 |
try: |
| 404 |
xdelta3main.main(args) |
| 405 |
except Exception, e: |
| 406 |
raise CommandError(args, "xdelta3.main exception") |
| 407 |
#end |
| 408 |
#end |
| 409 |
#end |
| 410 |
|
| 411 |
class Xdelta3Mod1: |
| 412 |
def __init__(self, file): |
| 413 |
self.target_data = open(file, 'r').read() |
| 414 |
#end |
| 415 |
|
| 416 |
def Encode(self, ignore1, ignore2, ignore3): |
| 417 |
r1, encoded = xdelta3.xd3_encode_memory(self.target_data, None, 1000000, 1<<10) |
| 418 |
if r1 != 0: |
| 419 |
raise CommandError('memory', 'encode failed: %s' % r1) |
| 420 |
#end |
| 421 |
self.encoded = encoded |
| 422 |
#end |
| 423 |
|
| 424 |
def Decode(self, ignore1, ignore2, ignore3): |
| 425 |
r2, data1 = xdelta3.xd3_decode_memory(self.encoded, None, len(self.target_data)) |
| 426 |
if r2 != 0: |
| 427 |
raise CommandError('memory', 'decode failed: %s' % r1) |
| 428 |
#end |
| 429 |
self.decoded = data1 |
| 430 |
#end |
| 431 |
|
| 432 |
def Verify(self, ignore1, ignore2): |
| 433 |
if self.target_data != self.decoded: |
| 434 |
raise CommandError('memory', 'bad decode') |
| 435 |
#end |
| 436 |
#end |
| 437 |
|
| 438 |
def EncodeSize(self, ignore1): |
| 439 |
return len(self.encoded) |
| 440 |
#end |
| 441 |
#end |
| 442 |
|
| 443 |
class GzipRun1: |
| 444 |
def Encode(self, target, source, output): |
| 445 |
assert source == None |
| 446 |
RunCommandIO(['gzip', '-cf'], target, output) |
| 447 |
#end |
| 448 |
|
| 449 |
def Decode(self, input, source, output): |
| 450 |
assert source == None |
| 451 |
RunCommandIO(['gzip', '-dcf'], input, output) |
| 452 |
#end |
| 453 |
|
| 454 |
def Verify(self, target, recon): |
| 455 |
RunCommand(('cmp', target, recon)) |
| 456 |
#end |
| 457 |
|
| 458 |
def EncodeSize(self, output): |
| 459 |
return os.stat(output).st_size |
| 460 |
#end |
| 461 |
#end |
| 462 |
|
| 463 |
class Xdelta1RunClass: |
| 464 |
def __str__(self): |
| 465 |
return 'xdelta1' |
| 466 |
#end |
| 467 |
|
| 468 |
def New(self): |
| 469 |
return Xdelta1Runner() |
| 470 |
#end |
| 471 |
#end |
| 472 |
|
| 473 |
class Xdelta1Runner: |
| 474 |
def Encode(self, target, source, output): |
| 475 |
assert source != None |
| 476 |
args = ['xdelta1', 'delta', '-q', source, target, output] |
| 477 |
RunCommand(args, [0, 1]) |
| 478 |
#end |
| 479 |
|
| 480 |
def Decode(self, input, source, output): |
| 481 |
assert source != None |
| 482 |
args = ['xdelta1', 'patch', '-q', input, source, output] |
| 483 |
# Note: for dumb historical reasons, xdelta1 returns 1 or 0 |
| 484 |
RunCommand(args) |
| 485 |
#end |
| 486 |
|
| 487 |
def Verify(self, target, recon): |
| 488 |
RunCommand(('cmp', target, recon)) |
| 489 |
#end |
| 490 |
|
| 491 |
def EncodeSize(self, output): |
| 492 |
return os.stat(output).st_size |
| 493 |
#end |
| 494 |
#end |
| 495 |
|
| 496 |
# exceptions |
| 497 |
class SkipRcsException: |
| 498 |
def __init__(self,reason): |
| 499 |
self.reason = reason |
| 500 |
#end |
| 501 |
#end |
| 502 |
|
| 503 |
class NotEnoughVersions: |
| 504 |
def __init__(self): |
| 505 |
pass |
| 506 |
#end |
| 507 |
#end |
| 508 |
|
| 509 |
class CommandError: |
| 510 |
def __init__(self,cmd,str): |
| 511 |
if type(cmd) is types.TupleType or \ |
| 512 |
type(cmd) is types.ListType: |
| 513 |
cmd = reduce(lambda x,y: '%s %s' % (x,y),cmd) |
| 514 |
#end |
| 515 |
print 'command was: ',cmd |
| 516 |
print 'command failed: ',str |
| 517 |
print 'have fun debugging' |
| 518 |
#end |
| 519 |
#end |
| 520 |
|
| 521 |
class RcsVersion: |
| 522 |
def __init__(self,vstr): |
| 523 |
self.vstr = vstr |
| 524 |
#end |
| 525 |
def __cmp__(self,other): |
| 526 |
return cmp(self.date, other.date) |
| 527 |
#end |
| 528 |
def __str__(self): |
| 529 |
return str(self.vstr) |
| 530 |
#end |
| 531 |
#end |
| 532 |
|
| 533 |
class RcsFile: |
| 534 |
|
| 535 |
def __init__(self, fname): |
| 536 |
self.fname = fname |
| 537 |
self.versions = [] |
| 538 |
self.state = HEAD_STATE |
| 539 |
#end |
| 540 |
|
| 541 |
def SetTotRev(self,s): |
| 542 |
self.totrev = int(s) |
| 543 |
#end |
| 544 |
|
| 545 |
def Rev(self,s): |
| 546 |
self.rev = RcsVersion(s) |
| 547 |
if len(self.versions) >= self.totrev: |
| 548 |
raise SkipRcsException('too many versions (in log messages)') |
| 549 |
#end |
| 550 |
self.versions.append(self.rev) |
| 551 |
#end |
| 552 |
|
| 553 |
def Date(self,s): |
| 554 |
self.rev.date = s |
| 555 |
#end |
| 556 |
|
| 557 |
def Match(self, line, state, rx, gp, newstate, f): |
| 558 |
if state == self.state: |
| 559 |
m = rx.match(line) |
| 560 |
if m: |
| 561 |
if f: |
| 562 |
f(m.group(gp)) |
| 563 |
#end |
| 564 |
self.state = newstate |
| 565 |
return 1 |
| 566 |
#end |
| 567 |
#end |
| 568 |
return None |
| 569 |
#end |
| 570 |
|
| 571 |
def Sum1Rlog(self): |
| 572 |
f = os.popen('rlog '+self.fname, "r") |
| 573 |
l = f.readline() |
| 574 |
while l: |
| 575 |
if self.Match(l, HEAD_STATE, RE_TOTREV, 1, BAR_STATE, self.SetTotRev): |
| 576 |
pass |
| 577 |
elif self.Match(l, BAR_STATE, RE_BAR, 1, REV_STATE, None): |
| 578 |
pass |
| 579 |
elif self.Match(l, REV_STATE, RE_REV, 1, DATE_STATE, self.Rev): |
| 580 |
pass |
| 581 |
elif self.Match(l, DATE_STATE, RE_DATE, 1, BAR_STATE, self.Date): |
| 582 |
pass |
| 583 |
#end |
| 584 |
l = f.readline() |
| 585 |
#end |
| 586 |
c = f.close() |
| 587 |
if c != None: |
| 588 |
raise c |
| 589 |
#end |
| 590 |
#end |
| 591 |
|
| 592 |
def Sum1(self): |
| 593 |
st = os.stat(self.fname) |
| 594 |
self.rcssize = st.st_size |
| 595 |
self.Sum1Rlog() |
| 596 |
if self.totrev != len(self.versions): |
| 597 |
raise SkipRcsException('wrong version count') |
| 598 |
#end |
| 599 |
self.versions.sort() |
| 600 |
#end |
| 601 |
|
| 602 |
def Checkout(self,n): |
| 603 |
v = self.versions[n] |
| 604 |
out = open(self.Verf(n), "w") |
| 605 |
cmd = 'co -ko -p%s %s' % (v.vstr, self.fname) |
| 606 |
total = 0 |
| 607 |
(inf, |
| 608 |
stream, |
| 609 |
err) = os.popen3(cmd, "r") |
| 610 |
inf.close() |
| 611 |
buf = stream.read() |
| 612 |
while buf: |
| 613 |
total = total + len(buf) |
| 614 |
out.write(buf) |
| 615 |
buf = stream.read() |
| 616 |
#end |
| 617 |
v.vsize = total |
| 618 |
estr = '' |
| 619 |
buf = err.read() |
| 620 |
while buf: |
| 621 |
estr = estr + buf |
| 622 |
buf = err.read() |
| 623 |
#end |
| 624 |
if stream.close(): |
| 625 |
raise CommandError(cmd, 'checkout failed: %s\n%s\n%s' % (v.vstr, self.fname, estr)) |
| 626 |
#end |
| 627 |
out.close() |
| 628 |
err.close() |
| 629 |
#end |
| 630 |
|
| 631 |
def Vdate(self,n): |
| 632 |
return self.versions[n].date |
| 633 |
#end |
| 634 |
|
| 635 |
def Vstr(self,n): |
| 636 |
return self.versions[n].vstr |
| 637 |
#end |
| 638 |
|
| 639 |
def Verf(self,n): |
| 640 |
return os.path.join(TMPDIR, 'input.%d' % n) |
| 641 |
#end |
| 642 |
|
| 643 |
def FilePairsByDate(self, runclass): |
| 644 |
if self.totrev < 2: |
| 645 |
raise NotEnoughVersions() |
| 646 |
#end |
| 647 |
self.Checkout(0) |
| 648 |
ntrials = [] |
| 649 |
if self.totrev < 2: |
| 650 |
return vtrials |
| 651 |
#end |
| 652 |
for v in range(0,self.totrev-1): |
| 653 |
if v > 1: |
| 654 |
os.remove(self.Verf(v-1)) |
| 655 |
#end |
| 656 |
self.Checkout(v+1) |
| 657 |
if os.stat(self.Verf(v)).st_size < MIN_SIZE or \ |
| 658 |
os.stat(self.Verf(v+1)).st_size < MIN_SIZE: |
| 659 |
continue |
| 660 |
#end |
| 661 |
|
| 662 |
result = TimedTest(self.Verf(v+1), |
| 663 |
self.Verf(v), |
| 664 |
runclass.New()) |
| 665 |
|
| 666 |
target_size = os.stat(self.Verf(v+1)).st_size |
| 667 |
|
| 668 |
ntrials.append(result) |
| 669 |
#end |
| 670 |
|
| 671 |
os.remove(self.Verf(self.totrev-1)) |
| 672 |
os.remove(self.Verf(self.totrev-2)) |
| 673 |
return ntrials |
| 674 |
#end |
| 675 |
|
| 676 |
def AppendVersion(self, f, n): |
| 677 |
self.Checkout(n) |
| 678 |
rf = open(self.Verf(n), "r") |
| 679 |
data = rf.read() |
| 680 |
f.write(data) |
| 681 |
rf.close() |
| 682 |
return len(data) |
| 683 |
#end |
| 684 |
|
| 685 |
class RcsFinder: |
| 686 |
def __init__(self): |
| 687 |
self.subdirs = [] |
| 688 |
self.rcsfiles = [] |
| 689 |
self.others = [] |
| 690 |
self.skipped = [] |
| 691 |
self.biground = 0 |
| 692 |
#end |
| 693 |
|
| 694 |
def Scan1(self,dir): |
| 695 |
dents = os.listdir(dir) |
| 696 |
subdirs = [] |
| 697 |
rcsfiles = [] |
| 698 |
others = [] |
| 699 |
for dent in dents: |
| 700 |
full = os.path.join(dir, dent) |
| 701 |
if os.path.isdir(full): |
| 702 |
subdirs.append(full) |
| 703 |
elif dent[len(dent)-2:] == ",v": |
| 704 |
rcsfiles.append(RcsFile(full)) |
| 705 |
else: |
| 706 |
others.append(full) |
| 707 |
#end |
| 708 |
#end |
| 709 |
self.subdirs = self.subdirs + subdirs |
| 710 |
self.rcsfiles = self.rcsfiles + rcsfiles |
| 711 |
self.others = self.others + others |
| 712 |
return subdirs |
| 713 |
#end |
| 714 |
|
| 715 |
def Crawl(self, dir): |
| 716 |
subdirs = [dir] |
| 717 |
while subdirs: |
| 718 |
s1 = self.Scan1(subdirs[0]) |
| 719 |
subdirs = subdirs[1:] + s1 |
| 720 |
#end |
| 721 |
#end |
| 722 |
|
| 723 |
def Summarize(self): |
| 724 |
good = [] |
| 725 |
for rf in self.rcsfiles: |
| 726 |
try: |
| 727 |
rf.Sum1() |
| 728 |
if rf.totrev < 2: |
| 729 |
raise SkipRcsException('too few versions (< 2)') |
| 730 |
#end |
| 731 |
except SkipRcsException, e: |
| 732 |
#print 'skipping file %s: %s' % (rf.fname, e.reason) |
| 733 |
self.skipped.append(rf) |
| 734 |
else: |
| 735 |
good.append(rf) |
| 736 |
#end |
| 737 |
self.rcsfiles = good |
| 738 |
#end |
| 739 |
|
| 740 |
def AllPairsByDate(self, runclass): |
| 741 |
results = [] |
| 742 |
good = [] |
| 743 |
for rf in self.rcsfiles: |
| 744 |
try: |
| 745 |
results = results + rf.FilePairsByDate(runclass) |
| 746 |
except SkipRcsException: |
| 747 |
print 'file %s has compressed versions: skipping' % (rf.fname) |
| 748 |
except NotEnoughVersions: |
| 749 |
print 'testing %s on %s: not enough versions' % (runclass, rf.fname) |
| 750 |
else: |
| 751 |
good.append(rf) |
| 752 |
#end |
| 753 |
self.rcsfiles = good |
| 754 |
self.ReportPairs(runclass, results) |
| 755 |
return results |
| 756 |
#end |
| 757 |
|
| 758 |
def ReportPairs(self, name, results): |
| 759 |
encode_time = 0 |
| 760 |
decode_time = 0 |
| 761 |
encode_size = 0 |
| 762 |
for r in results: |
| 763 |
encode_time += r.encode_time.mean |
| 764 |
decode_time += r.decode_time.mean |
| 765 |
encode_size += r.encode_size |
| 766 |
#end |
| 767 |
print '%s rcs: encode %.2f s: decode %.2f s: size %d' % \ |
| 768 |
(name, encode_time, decode_time, encode_size) |
| 769 |
#end |
| 770 |
|
| 771 |
def MakeBigFiles(self, rand): |
| 772 |
f1 = open(TMPDIR + "/big.1", "w") |
| 773 |
f2 = open(TMPDIR + "/big.2", "w") |
| 774 |
population = [] |
| 775 |
for file in self.rcsfiles: |
| 776 |
if len(file.versions) < 2: |
| 777 |
continue |
| 778 |
population.append(file) |
| 779 |
#end |
| 780 |
f1sz = 0 |
| 781 |
f2sz = 0 |
| 782 |
fcount = int(len(population) * FILE_P) |
| 783 |
assert fcount > 0 |
| 784 |
for file in rand.sample(population, fcount): |
| 785 |
m = IGNORE_FILENAME.match(file.fname) |
| 786 |
if m != None: |
| 787 |
continue |
| 788 |
#end |
| 789 |
r1, r2 = rand.sample(xrange(0, len(file.versions)), 2) |
| 790 |
f1sz += file.AppendVersion(f1, r1) |
| 791 |
f2sz += file.AppendVersion(f2, r2) |
| 792 |
#m.update('%s,%s,%s ' % (file.fname[len(RCSDIR):], file.Vstr(r1), file.Vstr(r2))) |
| 793 |
#end |
| 794 |
testkey = 'rcs%d' % self.biground |
| 795 |
self.biground = self.biground + 1 |
| 796 |
|
| 797 |
print '%s; source %u bytes; target %u bytes' % (testkey, f1sz, f2sz) |
| 798 |
f1.close() |
| 799 |
f2.close() |
| 800 |
return (TMPDIR + "/big.1", |
| 801 |
TMPDIR + "/big.2", |
| 802 |
testkey) |
| 803 |
#end |
| 804 |
|
| 805 |
def Generator(self): |
| 806 |
return lambda rand: self.MakeBigFiles(rand) |
| 807 |
#end |
| 808 |
#end |
| 809 |
|
| 810 |
# find a set of RCS files for testing |
| 811 |
def GetTestRcsFiles(): |
| 812 |
rcsf = RcsFinder() |
| 813 |
rcsf.Crawl(RCSDIR) |
| 814 |
if len(rcsf.rcsfiles) == 0: |
| 815 |
raise CommandError('', 'no RCS files') |
| 816 |
#end |
| 817 |
rcsf.Summarize() |
| 818 |
print "rcsfiles: rcsfiles %d; subdirs %d; others %d; skipped %d" % (len(rcsf.rcsfiles), |
| 819 |
len(rcsf.subdirs), |
| 820 |
len(rcsf.others), |
| 821 |
len(rcsf.skipped)) |
| 822 |
print StatList([x.rcssize for x in rcsf.rcsfiles], "rcssize").str |
| 823 |
print StatList([x.totrev for x in rcsf.rcsfiles], "totrev").str |
| 824 |
return rcsf |
| 825 |
#end |
| 826 |
|
| 827 |
class SampleDataTest: |
| 828 |
def __init__(self, dirs): |
| 829 |
self.pairs = [] |
| 830 |
while dirs: |
| 831 |
d = dirs[0] |
| 832 |
dirs = dirs[1:] |
| 833 |
l = os.listdir(d) |
| 834 |
files = [] |
| 835 |
for e in l: |
| 836 |
p = os.path.join(d, e) |
| 837 |
if os.path.isdir(p): |
| 838 |
dirs.append(p) |
| 839 |
else: |
| 840 |
files.append(p) |
| 841 |
#end |
| 842 |
#end |
| 843 |
if len(files) > 1: |
| 844 |
files.sort() |
| 845 |
for x in xrange(len(files) - 1): |
| 846 |
self.pairs.append((files[x], files[x+1], |
| 847 |
'%s-%s' % (files[x], files[x+1]))) |
| 848 |
#end |
| 849 |
#end |
| 850 |
#end |
| 851 |
#end |
| 852 |
|
| 853 |
def Generator(self): |
| 854 |
return lambda rand: rand.choice(self.pairs) |
| 855 |
#end |
| 856 |
#end |
| 857 |
|
| 858 |
# configs are represented as a list of values, |
| 859 |
# program takes a list of strings: |
| 860 |
def ConfigToArgs(config): |
| 861 |
args = [ '-C', |
| 862 |
','.join([str(x) for x in config[0:SOFT_CONFIG_CNT]])] |
| 863 |
for i in range(SOFT_CONFIG_CNT, len(CONFIG_ORDER)): |
| 864 |
key = CONFIG_ARGMAP[CONFIG_ORDER[i]] |
| 865 |
val = config[i] |
| 866 |
if val == 'true' or val == 'false': |
| 867 |
if val == 'true': |
| 868 |
args.append('%s' % key) |
| 869 |
#end |
| 870 |
else: |
| 871 |
args.append('%s=%s' % (key, val)) |
| 872 |
#end |
| 873 |
#end |
| 874 |
return args |
| 875 |
#end |
| 876 |
|
| 877 |
# |
| 878 |
class RandomTest: |
| 879 |
def __init__(self, tnum, tinput, config, syntuple = None): |
| 880 |
self.mytinput = tinput[2] |
| 881 |
self.myconfig = config |
| 882 |
self.tnum = tnum |
| 883 |
|
| 884 |
if syntuple != None: |
| 885 |
self.runtime = syntuple[0] |
| 886 |
self.compsize = syntuple[1] |
| 887 |
self.decodetime = None |
| 888 |
else: |
| 889 |
args = ConfigToArgs(config) |
| 890 |
result = TimedTest(tinput[1], tinput[0], Xdelta3Runner(args)) |
| 891 |
|
| 892 |
self.runtime = result.encode_time.mean |
| 893 |
self.compsize = result.encode_size |
| 894 |
self.decodetime = result.decode_time.mean |
| 895 |
#end |
| 896 |
|
| 897 |
self.score = None |
| 898 |
self.time_pos = None |
| 899 |
self.size_pos = None |
| 900 |
self.score_pos = None |
| 901 |
#end |
| 902 |
|
| 903 |
def __str__(self): |
| 904 |
decodestr = '' |
| 905 |
if not SKIP_DECODE: |
| 906 |
decodestr = ' %.6f' % self.decodetime |
| 907 |
#end |
| 908 |
return 'time %.6f%s size %d%s << %s >>%s' % ( |
| 909 |
self.time(), ((self.time_pos != None) and (" (%s)" % self.time_pos) or ""), |
| 910 |
self.size(), ((self.size_pos != None) and (" (%s)" % self.size_pos) or ""), |
| 911 |
c2str(self.config()), |
| 912 |
decodestr) |
| 913 |
#end |
| 914 |
|
| 915 |
def time(self): |
| 916 |
return self.runtime |
| 917 |
#end |
| 918 |
|
| 919 |
def size(self): |
| 920 |
return self.compsize |
| 921 |
#end |
| 922 |
|
| 923 |
def config(self): |
| 924 |
return self.myconfig |
| 925 |
#end |
| 926 |
|
| 927 |
def score(self): |
| 928 |
return self.score |
| 929 |
#end |
| 930 |
|
| 931 |
def tinput(self): |
| 932 |
return self.mytinput |
| 933 |
#end |
| 934 |
#end |
| 935 |
|
| 936 |
def PosInAlist(l, e): |
| 937 |
for i in range(0, len(l)): |
| 938 |
if l[i][1] == e: |
| 939 |
return i; |
| 940 |
#end |
| 941 |
#end |
| 942 |
return -1 |
| 943 |
#end |
| 944 |
|
| 945 |
# Generates a set of num_results test configurations, given the list of |
| 946 |
# retest-configs. |
| 947 |
def RandomTestConfigs(rand, input_configs, num_results): |
| 948 |
|
| 949 |
outputs = input_configs[:] |
| 950 |
have_set = dict([(c,c) for c in input_configs]) |
| 951 |
|
| 952 |
# Compute a random configuration |
| 953 |
def RandomConfig(): |
| 954 |
config = [] |
| 955 |
cmap = {} |
| 956 |
for key in CONFIG_ORDER: |
| 957 |
val = cmap[key] = (INPUT_SPEC(rand)[key])(cmap) |
| 958 |
config.append(val) |
| 959 |
#end |
| 960 |
return tuple(config) |
| 961 |
#end |
| 962 |
|
| 963 |
while len(outputs) < num_results: |
| 964 |
newc = None |
| 965 |
for i in xrange(10): |
| 966 |
c = RandomConfig() |
| 967 |
if have_set.has_key(c): |
| 968 |
continue |
| 969 |
#end |
| 970 |
have_set[c] = c |
| 971 |
newc = c |
| 972 |
break |
| 973 |
if newc is None: |
| 974 |
print 'stopped looking for configs at %d' % len(outputs) |
| 975 |
break |
| 976 |
#end |
| 977 |
outputs.append(c) |
| 978 |
#end |
| 979 |
outputs.sort() |
| 980 |
return outputs |
| 981 |
#end |
| 982 |
|
| 983 |
def RunTestLoop(rand, generator, rounds): |
| 984 |
configs = [] |
| 985 |
for rnum in xrange(rounds): |
| 986 |
configs = RandomTestConfigs(rand, configs, MAX_RESULTS) |
| 987 |
tinput = generator(rand) |
| 988 |
tests = [] |
| 989 |
for x in xrange(len(configs)): |
| 990 |
t = RandomTest(x, tinput, configs[x]) |
| 991 |
print 'Round %d test %d: %s' % (rnum, x, t) |
| 992 |
tests.append(t) |
| 993 |
#end |
| 994 |
results = ScoreTests(tests) |
| 995 |
|
| 996 |
for r in results: |
| 997 |
c = r.config() |
| 998 |
if not test_all_config_results.has_key(c): |
| 999 |
test_all_config_results[c] = [r] |
| 1000 |
else: |
| 1001 |
test_all_config_results[c].append(r) |
| 1002 |
#end |
| 1003 |
#end |
| 1004 |
|
| 1005 |
GraphResults('expt%d' % rnum, results) |
| 1006 |
GraphSummary('sum%d' % rnum, results) |
| 1007 |
|
| 1008 |
# re-test some fraction |
| 1009 |
configs = [r.config() for r in results[0:int(MAX_RESULTS * KEEP_P)]] |
| 1010 |
#end |
| 1011 |
#end |
| 1012 |
|
| 1013 |
# TODO: cleanup |
| 1014 |
test_all_config_results = {} |
| 1015 |
|
| 1016 |
def ScoreTests(results): |
| 1017 |
scored = [] |
| 1018 |
timed = [] |
| 1019 |
sized = [] |
| 1020 |
|
| 1021 |
t_min = float(min([test.time() for test in results])) |
| 1022 |
#t_max = float(max([test.time() for test in results])) |
| 1023 |
s_min = float(min([test.size() for test in results])) |
| 1024 |
#s_max = float(max([test.size() for test in results])) |
| 1025 |
|
| 1026 |
for test in results: |
| 1027 |
|
| 1028 |
# Hyperbolic function. Smaller scores still better |
| 1029 |
red = 0.999 # minimum factors for each dimension are 1/1000 |
| 1030 |
test.score = ((test.size() - s_min * red) * |
| 1031 |
(test.time() - t_min * red)) |
| 1032 |
|
| 1033 |
scored.append((test.score, test)) |
| 1034 |
timed.append((test.time(), test)) |
| 1035 |
sized.append((test.size(), test)) |
| 1036 |
#end |
| 1037 |
|
| 1038 |
scored.sort() |
| 1039 |
timed.sort() |
| 1040 |
sized.sort() |
| 1041 |
|
| 1042 |
best_by_size = [] |
| 1043 |
best_by_time = [] |
| 1044 |
|
| 1045 |
pos = 0 |
| 1046 |
for (score, test) in scored: |
| 1047 |
pos += 1 |
| 1048 |
test.score_pos = pos |
| 1049 |
#end |
| 1050 |
|
| 1051 |
scored = [x[1] for x in scored] |
| 1052 |
|
| 1053 |
for test in scored: |
| 1054 |
test.size_pos = PosInAlist(sized, test) |
| 1055 |
test.time_pos = PosInAlist(timed, test) |
| 1056 |
#end |
| 1057 |
|
| 1058 |
for test in scored: |
| 1059 |
c = test.config() |
| 1060 |
s = 0.0 |
| 1061 |
print 'H-Score: %0.9f %s' % (test.score, test) |
| 1062 |
#end |
| 1063 |
|
| 1064 |
return scored |
| 1065 |
#end |
| 1066 |
|
| 1067 |
def GraphResults(desc, results): |
| 1068 |
f = open("data-%s.csv" % desc, "w") |
| 1069 |
for r in results: |
| 1070 |
f.write("%0.9f\t%d\t# %s\n" % (r.time(), r.size(), r)) |
| 1071 |
#end |
| 1072 |
f.close() |
| 1073 |
os.system("./plot.sh data-%s.csv plot-%s.jpg" % (desc, desc)) |
| 1074 |
#end |
| 1075 |
|
| 1076 |
def GraphSummary(desc, results_ignore): |
| 1077 |
test_population = 0 |
| 1078 |
config_ordered = [] |
| 1079 |
|
| 1080 |
# drops duplicate test/config pairs (TODO: don't retest them) |
| 1081 |
for config, cresults in test_all_config_results.items(): |
| 1082 |
input_config_map = {} |
| 1083 |
uniq = [] |
| 1084 |
for test in cresults: |
| 1085 |
assert test.config() == config |
| 1086 |
test_population += 1 |
| 1087 |
key = test.tinput() |
| 1088 |
if not input_config_map.has_key(key): |
| 1089 |
input_config_map[key] = {} |
| 1090 |
#end |
| 1091 |
if input_config_map[key].has_key(config): |
| 1092 |
print 'skipping repeat test %s vs. %s' % (input_config_map[key][config], test) |
| 1093 |
continue |
| 1094 |
#end |
| 1095 |
input_config_map[key][config] = test |
| 1096 |
uniq.append(test) |
| 1097 |
#end |
| 1098 |
config_ordered.append(uniq) |
| 1099 |
#end |
| 1100 |
|
| 1101 |
# sort configs descending by number of tests |
| 1102 |
config_ordered.sort(lambda x, y: len(y) - len(x)) |
| 1103 |
|
| 1104 |
print 'population %d: %d configs %d results' % \ |
| 1105 |
(test_population, |
| 1106 |
len(config_ordered), |
| 1107 |
len(config_ordered[0])) |
| 1108 |
|
| 1109 |
if config_ordered[0] == 1: |
| 1110 |
return |
| 1111 |
#end |
| 1112 |
|
| 1113 |
# a map from test-key to test-list w/ various configs |
| 1114 |
input_set = {} |
| 1115 |
osize = len(config_ordered) |
| 1116 |
|
| 1117 |
for i in xrange(len(config_ordered)): |
| 1118 |
config = config_ordered[i][0].config() |
| 1119 |
config_tests = config_ordered[i] |
| 1120 |
|
| 1121 |
#print '%s has %d tested inputs' % (config, len(config_tests)) |
| 1122 |
|
| 1123 |
if len(input_set) == 0: |
| 1124 |
input_set = dict([(t.tinput(), [t]) for t in config_tests]) |
| 1125 |
continue |
| 1126 |
#end |
| 1127 |
|
| 1128 |
# a map from test-key to test-list w/ various configs |
| 1129 |
update_set = {} |
| 1130 |
for r in config_tests: |
| 1131 |
t = r.tinput() |
| 1132 |
if input_set.has_key(t): |
| 1133 |
update_set[t] = input_set[t] + [r] |
| 1134 |
else: |
| 1135 |
#print 'config %s does not have test %s' % (config, t) |
| 1136 |
pass |
| 1137 |
#end |
| 1138 |
#end |
| 1139 |
|
| 1140 |
if len(update_set) <= 1: |
| 1141 |
break |
| 1142 |
#end |
| 1143 |
|
| 1144 |
input_set = update_set |
| 1145 |
|
| 1146 |
# continue if there are more w/ the same number of inputs |
| 1147 |
if i < (len(config_ordered) - 1) and \ |
| 1148 |
len(config_ordered[i + 1]) == len(config_tests): |
| 1149 |
continue |
| 1150 |
#end |
| 1151 |
|
| 1152 |
# synthesize results for multi-test inputs |
| 1153 |
config_num = None |
| 1154 |
|
| 1155 |
# map of config to sum(various test-keys) |
| 1156 |
smap = {} |
| 1157 |
for (key, tests) in input_set.items(): |
| 1158 |
if config_num == None: |
| 1159 |
# config_num should be the same in all elements |
| 1160 |
config_num = len(tests) |
| 1161 |
smap = dict([(r.config(), |
| 1162 |
(r.time(), |
| 1163 |
r.size())) |
| 1164 |
for r in tests]) |
| 1165 |
else: |
| 1166 |
# compuate the per-config sum of time/size |
| 1167 |
assert config_num == len(tests) |
| 1168 |
smap = dict([(r.config(), |
| 1169 |
(smap[r.config()][0] + r.time(), |
| 1170 |
smap[r.config()][1] + r.size())) |
| 1171 |
for r in tests]) |
| 1172 |
#end |
| 1173 |
#end |
| 1174 |
|
| 1175 |
if config_num == 1: |
| 1176 |
continue |
| 1177 |
#end |
| 1178 |
|
| 1179 |
if len(input_set) == osize: |
| 1180 |
break |
| 1181 |
#end |
| 1182 |
|
| 1183 |
summary = '%s-%d' % (desc, len(input_set)) |
| 1184 |
osize = len(input_set) |
| 1185 |
|
| 1186 |
print 'generate %s w/ %d configs' % (summary, config_num) |
| 1187 |
syn = [RandomTest(0, (None, None, summary), config, |
| 1188 |
syntuple = (smap[config][0], smap[config][1])) |
| 1189 |
for config in smap.keys()] |
| 1190 |
syn = ScoreTests(syn) |
| 1191 |
#print 'smap is %s' % (smap,) |
| 1192 |
#print 'syn is %s' % (' and '.join([str(x) for x in syn])) |
| 1193 |
GraphResults(summary, syn) |
| 1194 |
#end |
| 1195 |
#end |
| 1196 |
|
| 1197 |
if __name__ == "__main__": |
| 1198 |
try: |
| 1199 |
RunCommand(['rm', '-rf', TMPDIR]) |
| 1200 |
os.mkdir(TMPDIR) |
| 1201 |
|
| 1202 |
rcsf = GetTestRcsFiles() |
| 1203 |
generator = rcsf.Generator() |
| 1204 |
|
| 1205 |
#sample = SampleDataTest([SAMPLEDIR]) |
| 1206 |
#generator = sample.Generator() |
| 1207 |
|
| 1208 |
rand = random.Random(135135135135135) |
| 1209 |
RunTestLoop(rand, generator, TEST_ROUNDS) |
| 1210 |
|
| 1211 |
#RunSpeedTest() |
| 1212 |
|
| 1213 |
#x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9'])) |
| 1214 |
#x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-S', 'djw'])) |
| 1215 |
#x3r = rcsf.AllPairsByDate(Xdelta3RunClass(['-9', '-T'])) |
| 1216 |
|
| 1217 |
#x1r = rcsf.AllPairsByDate(Xdelta1RunClass()) |
| 1218 |
|
| 1219 |
except CommandError: |
| 1220 |
pass |
| 1221 |
else: |
| 1222 |
RunCommand(['rm', '-rf', TMPDIR]) |
| 1223 |
pass |
| 1224 |
#end |
| 1225 |
#end |