]> arthur.barton.de Git - bup.git/blob - cmd/memtest-cmd.py
894bb64366a20543cc50d2bcce3874871ca3eec3
[bup.git] / cmd / memtest-cmd.py
1 #!/bin/sh
2 """": # -*-python-*-
3 bup_python="$(dirname "$0")/bup-python" || exit $?
4 exec "$bup_python" "$0" ${1+"$@"}
5 """
6 # end of bup preamble
7
8 from __future__ import absolute_import
9 import sys, re, struct, time, resource
10
11 from bup import git, bloom, midx, options, _helpers
12 from bup.helpers import handle_ctrl_c
13
14
15 handle_ctrl_c()
16
17
18 _linux_warned = 0
19 def linux_memstat():
20     global _linux_warned
21     #fields = ['VmSize', 'VmRSS', 'VmData', 'VmStk', 'ms']
22     d = {}
23     try:
24         f = open('/proc/self/status')
25     except IOError as e:
26         if not _linux_warned:
27             log('Warning: %s\n' % e)
28             _linux_warned = 1
29         return {}
30     for line in f:
31         # Note that on Solaris, this file exists but is binary.  If that
32         # happens, this split() might not return two elements.  We don't
33         # really need to care about the binary format since this output
34         # isn't used for much and report() can deal with missing entries.
35         t = re.split(r':\s*', line.strip(), 1)
36         if len(t) == 2:
37             k,v = t
38             d[k] = v
39     return d
40
41
42 last = last_u = last_s = start = 0
43 def report(count):
44     global last, last_u, last_s, start
45     headers = ['RSS', 'MajFlt', 'user', 'sys', 'ms']
46     ru = resource.getrusage(resource.RUSAGE_SELF)
47     now = time.time()
48     rss = int(ru.ru_maxrss/1024)
49     if not rss:
50         rss = linux_memstat().get('VmRSS', '??')
51     fields = [rss,
52               ru.ru_majflt,
53               int((ru.ru_utime - last_u) * 1000),
54               int((ru.ru_stime - last_s) * 1000),
55               int((now - last) * 1000)]
56     fmt = '%9s  ' + ('%10s ' * len(fields))
57     if count >= 0:
58         print fmt % tuple([count] + fields)
59     else:
60         start = now
61         print fmt % tuple([''] + headers)
62     sys.stdout.flush()
63     
64     # don't include time to run report() in usage counts
65     ru = resource.getrusage(resource.RUSAGE_SELF)
66     last_u = ru.ru_utime
67     last_s = ru.ru_stime
68     last = time.time()
69
70
71 optspec = """
72 bup memtest [-n elements] [-c cycles]
73 --
74 n,number=  number of objects per cycle [10000]
75 c,cycles=  number of cycles to run [100]
76 ignore-midx  ignore .midx files, use only .idx files
77 existing   test with existing objects instead of fake ones
78 """
79 o = options.Options(optspec)
80 (opt, flags, extra) = o.parse(sys.argv[1:])
81
82 if extra:
83     o.fatal('no arguments expected')
84
85 git.ignore_midx = opt.ignore_midx
86
87 git.check_repo_or_die()
88 m = git.PackIdxList(git.repo('objects/pack'))
89
90 report(-1)
91 _helpers.random_sha()
92 report(0)
93
94 if opt.existing:
95     def foreverit(mi):
96         while 1:
97             for e in mi:
98                 yield e
99     objit = iter(foreverit(m))
100     
101 for c in xrange(opt.cycles):
102     for n in xrange(opt.number):
103         if opt.existing:
104             bin = next(objit)
105             assert(m.exists(bin))
106         else:
107             bin = _helpers.random_sha()
108
109             # technically, a randomly generated object id might exist.
110             # but the likelihood of that is the likelihood of finding
111             # a collision in sha-1 by accident, which is so unlikely that
112             # we don't care.
113             assert(not m.exists(bin))
114     report((c+1)*opt.number)
115
116 if bloom._total_searches:
117     print ('bloom: %d objects searched in %d steps: avg %.3f steps/object' 
118            % (bloom._total_searches, bloom._total_steps,
119               bloom._total_steps*1.0/bloom._total_searches))
120 if midx._total_searches:
121     print ('midx: %d objects searched in %d steps: avg %.3f steps/object' 
122            % (midx._total_searches, midx._total_steps,
123               midx._total_steps*1.0/midx._total_searches))
124 if git._total_searches:
125     print ('idx: %d objects searched in %d steps: avg %.3f steps/object' 
126            % (git._total_searches, git._total_steps,
127               git._total_steps*1.0/git._total_searches))
128 print 'Total time: %.3fs' % (time.time() - start)