twisterp2pblockchainnetworkbittorrentmicrobloggingipv6social-networkdhtdecentralizedp2p-networktwister-servertwister-ipv6twister-coretwisterarmy
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
192 lines
5.1 KiB
192 lines
5.1 KiB
#! /usr/bin/env python |
|
import sys |
|
import os |
|
import time |
|
import calendar |
|
|
|
up_time_quanta = 2000 |
|
|
|
f = open(sys.argv[1]) |
|
|
|
announce_histogram = {} |
|
node_uptime_histogram = {} |
|
|
|
counter = 0; |
|
|
|
# maps search_id to a list of events. Each event is a dict containing: |
|
# t: timestamp |
|
# d: distance (from target) |
|
# o: outstanding searches |
|
# e: event (NEW, COMPLETED, ADD, INVOKE, TIMEOUT) |
|
outstanding_searches = {} |
|
|
|
# list of completed searches |
|
searches = [] |
|
|
|
def convert_timestamp(t): |
|
parts = t.split('.') |
|
posix = time.strptime(parts[0], '%H:%M:%S') |
|
return (posix.tm_hour * 3600 + posix.tm_min * 60 + posix.tm_sec) * 1000 + int(parts[1]) |
|
|
|
for line in f: |
|
counter += 1 |
|
# if counter % 1000 == 0: |
|
# print '\r%d' % counter, |
|
try: |
|
l = line.split(' ') |
|
if 'announce-distance:' in line: |
|
idx = l.index('announce-distance:') |
|
|
|
d = int(l[idx+1].strip()) |
|
if not d in announce_histogram: announce_histogram[d] = 0 |
|
announce_histogram[d] += 1 |
|
if 'NODE FAILED' in line: |
|
idx = l.index('fails:') |
|
if int(l[idx+1].strip()) != 1: continue; |
|
idx = l.index('up-time:') |
|
d = int(l[idx+1].strip()) |
|
# quantize |
|
d = d - (d % up_time_quanta) |
|
if not d in node_uptime_histogram: node_uptime_histogram[d] = 0 |
|
node_uptime_histogram[d] += 1 |
|
|
|
search_id = l[2] |
|
ts = l[0] |
|
event = l[3] |
|
|
|
if event == 'NEW': |
|
outstanding_searches[search_id] = [{ 't': ts, 'd': 160, 'o': 0, 'e': 'NEW'}] |
|
elif event == 'INVOKE' or event == 'ADD' or event == '1ST_TIMEOUT' or event == 'TIMEOUT' or event == 'PEERS': |
|
if not search_id in outstanding_searches: |
|
print 'orphaned event: %s' % line |
|
else: |
|
outstanding = int(l[l.index('invoke-count:')+1]) |
|
distance = int(l[l.index('distance:')+1]) |
|
outstanding_searches[search_id].append({ 't': ts, 'd': distance, 'o': outstanding + 1, 'e': event}) |
|
elif event == 'COMPLETED': |
|
distance = int(l[l.index('distance:')+1]) |
|
outstanding_searches[search_id].append({ 't': ts, 'd': distance, 'o': 0, 'e': event}) |
|
|
|
s = outstanding_searches[search_id] |
|
|
|
try: |
|
start_time = convert_timestamp(s[0]['t']) |
|
for i in range(len(s)): |
|
s[i]['t'] = convert_timestamp(s[i]['t']) - start_time |
|
except: |
|
pass |
|
searches.append(s) |
|
del outstanding_searches[search_id] |
|
|
|
|
|
|
|
except Exception, e: |
|
print line.split(' ') |
|
|
|
lookup_times_min = [] |
|
lookup_times_max = [] |
|
for s in searches: |
|
for i in s: |
|
if i['e'] != 'PEERS': continue |
|
lookup_times_min.append(i['t']) |
|
break |
|
for i in reversed(s): |
|
if i['e'] != 'PEERS': continue |
|
lookup_times_max.append(i['t']) |
|
break |
|
|
|
lookup_times_min.sort() |
|
lookup_times_max.sort() |
|
out = open('dht_lookup_times_cdf.txt', 'w+') |
|
counter = 0 |
|
for i in range(len(lookup_times_min)): |
|
counter += 1 |
|
print >>out, '%d\t%d\t%f' % (lookup_times_min[i], lookup_times_max[i], counter / float(len(lookup_times_min))) |
|
out.close() |
|
|
|
out = open('dht_lookups.txt', 'w+') |
|
for s in searches: |
|
for i in s: |
|
if i['e'] == 'INVOKE': |
|
print >>out, ' ->', i['t'], i['d'] |
|
elif i['e'] == '1ST_TIMEOUT': |
|
print >>out, ' x ', i['t'], i['d'] |
|
elif i['e'] == 'TIMEOUT': |
|
print >>out, ' X ', i['t'], i['d'] |
|
elif i['e'] == 'PEERS': |
|
print >>out, ' <-', i['t'], i['d'] |
|
elif i['e'] == 'COMPLETED': |
|
print >>out, '***', i['t'], i['d'], '\n' |
|
break |
|
out.close() |
|
|
|
out = open('dht_announce_distribution.dat', 'w+') |
|
print 'announce distribution items: %d' % len(announce_histogram) |
|
for k,v in announce_histogram.items(): |
|
print >>out, '%d %d' % (k, v) |
|
print '%d %d' % (k, v) |
|
out.close() |
|
|
|
out = open('dht_node_uptime_distribution.dat', 'w+') |
|
print 'node uptimes: %d' % len(node_uptime_histogram) |
|
for k,v in node_uptime_histogram.items(): |
|
print >>out, '%d %d' % (k + up_time_quanta/2, v) |
|
out.close() |
|
|
|
out = open('dht.gnuplot', 'w+') |
|
out.write(''' |
|
set term png size 1200,700 small |
|
set output "dht_lookup_times_cdf.png" |
|
set title "portion of lookups that have received at least one data response" |
|
set ylabel "portion of lookups" |
|
set xlabel "time from start of lookup (ms)" |
|
set grid |
|
plot "dht_lookup_times_cdf.txt" using 1:3 with lines title "time to first result", \ |
|
"dht_lookup_times_cdf.txt" using 2:3 with lines title "time to last result" |
|
|
|
set terminal postscript |
|
set output "dht_lookup_times_cdf.ps" |
|
replot |
|
|
|
set term png size 1200,700 small |
|
set xtics 100 |
|
set xrange [0:2000] |
|
set output "dht_min_lookup_times_cdf.png" |
|
plot "dht_lookup_times_cdf.txt" using 1:3 with lines title "time to first result" |
|
|
|
set terminal postscript |
|
set output "dht_min_lookup_times_cdf.ps" |
|
replot |
|
|
|
set term png size 1200,700 small |
|
set output "dht_node_uptime_distribution.png" |
|
set xrange [*:*] |
|
set title "node up time" |
|
set ylabel "# of nodes" |
|
set xlabel "uptime (seconds)" |
|
set xtics auto |
|
unset grid |
|
set boxwidth %f |
|
set style fill solid border -1 pattern 2 |
|
plot "dht_node_uptime_distribution.dat" using 1:2 title "nodes" with boxes |
|
|
|
set term png size 1200,700 small |
|
set output "dht_announce_distribution.png" |
|
set xrange [0:*] |
|
set title "bucket # announces are made against relative to target node-id" |
|
set ylabel "# of announces" |
|
set style fill solid border -1 pattern 2 |
|
plot "dht_announce_distribution.dat" using 1:2 title "announces" with boxes |
|
|
|
set terminal postscript |
|
set output "dht_announce_distribution.ps" |
|
replot |
|
|
|
''' % up_time_quanta) |
|
|
|
|
|
out.close() |
|
|
|
os.system('gnuplot dht.gnuplot'); |
|
|
|
|
|
|