]> arthur.barton.de Git - bup.git/blob - cmd/margin-cmd.py
ac25ed0644a9049d76d259572890ac7262b6e638
[bup.git] / cmd / margin-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 import sys, struct, math
8 from bup import options, git, _helpers
9 from bup.helpers import *
10
11 POPULATION_OF_EARTH=6.7e9  # as of September, 2010
12
13 optspec = """
14 bup margin
15 --
16 predict    Guess object offsets and report the maximum deviation
17 ignore-midx  Don't use midx files; use only plain pack idx files.
18 """
19 o = options.Options(optspec)
20 (opt, flags, extra) = o.parse(sys.argv[1:])
21
22 if extra:
23     o.fatal("no arguments expected")
24
25 git.check_repo_or_die()
26 git.ignore_midx = opt.ignore_midx
27
28 mi = git.PackIdxList(git.repo('objects/pack'))
29
30 def do_predict(ix):
31     total = len(ix)
32     maxdiff = 0
33     for count,i in enumerate(ix):
34         prefix = struct.unpack('!Q', i[:8])[0]
35         expected = prefix * total / (1<<64)
36         diff = count - expected
37         maxdiff = max(maxdiff, abs(diff))
38     print '%d of %d (%.3f%%) ' % (maxdiff, len(ix), maxdiff*100.0/len(ix))
39     sys.stdout.flush()
40     assert(count+1 == len(ix))
41
42 if opt.predict:
43     if opt.ignore_midx:
44         for pack in mi.packs:
45             do_predict(pack)
46     else:
47         do_predict(mi)
48 else:
49     # default mode: find longest matching prefix
50     last = '\0'*20
51     longmatch = 0
52     for i in mi:
53         if i == last:
54             continue
55         #assert(str(i) >= last)
56         pm = _helpers.bitmatch(last, i)
57         longmatch = max(longmatch, pm)
58         last = i
59     print longmatch
60     log('%d matching prefix bits\n' % longmatch)
61     doublings = math.log(len(mi), 2)
62     bpd = longmatch / doublings
63     log('%.2f bits per doubling\n' % bpd)
64     remain = 160 - longmatch
65     rdoublings = remain / bpd
66     log('%d bits (%.2f doublings) remaining\n' % (remain, rdoublings))
67     larger = 2**rdoublings
68     log('%g times larger is possible\n' % larger)
69     perperson = larger/POPULATION_OF_EARTH
70     log('\nEveryone on earth could have %d data sets like yours, all in one\n'
71         'repository, and we would expect 1 object collision.\n'
72         % int(perperson))