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.
193 lines
5.1 KiB
193 lines
5.1 KiB
11 years ago
|
#! /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');
|
||
|
|
||
|
|