Update and rename MantenerFIFO to MantenerFIFO.md
[vsorcdistro/.git] / mininet / examples / cpu.py
1 #!/usr/bin/python
2
3 """
4 cpu.py: test iperf bandwidth for varying cpu limits
5
6 Since we are limiting the hosts (only), we should expect the iperf
7 processes to be affected, as well as any system processing which is
8 billed to the hosts.
9
10 We reserve >50% of cycles for system processing; we assume that
11 this is enough for it not to affect results. Hosts are limited to
12 40% of total cycles, which we assume is enough to make them CPU
13 bound.
14
15 As CPU performance increases over time, we may have to reduce the
16 overall CPU allocation so that the host processing is still CPU bound.
17 This is perhaps an argument for specifying performance in a more
18 system-independent manner.
19
20 It would also be nice to have a better handle on limiting packet
21 processing cycles. It's not entirely clear to me how those are
22 billed to user or system processes if we are using OVS with a kernel
23 datapath. With a user datapath, they are easier to account for, but
24 overall performance is usually lower.
25
26 Although the iperf client uses more CPU and should be CPU bound (?),
27 we measure the received data at the server since the client transmit
28 rate includes buffering.
29 """
30
31 from mininet.net import Mininet
32 from mininet.node import CPULimitedHost
33 from mininet.topolib import TreeTopo
34 from mininet.util import custom, waitListening, decode
35 from mininet.log import setLogLevel, info
36 from mininet.clean import cleanup
37
38 def bwtest( cpuLimits, period_us=100000, seconds=10 ):
39     """Example/test of link and CPU bandwidth limits
40        cpu: cpu limit as fraction of overall CPU time"""
41
42     topo = TreeTopo( depth=1, fanout=2 )
43
44     results = {}
45
46     for sched in 'rt', 'cfs':
47         info( '*** Testing with', sched, 'bandwidth limiting\n' )
48         for cpu in cpuLimits:
49             # cpu is the cpu fraction for all hosts, so we divide
50             # it across two hosts
51             host = custom( CPULimitedHost, sched=sched,
52                            period_us=period_us,
53                            cpu=.5*cpu )
54             try:
55                 net = Mininet( topo=topo, host=host )
56             # pylint: disable=bare-except
57             except:
58                 info( '*** Skipping scheduler %s and cleaning up\n' % sched )
59                 cleanup()
60                 break
61             net.start()
62             net.pingAll()
63             hosts = [ net.getNodeByName( h ) for h in topo.hosts() ]
64             client, server = hosts[ 0 ], hosts[ -1 ]
65             info( '*** Starting iperf with %d%% of CPU allocated to hosts\n' %
66                   ( 100.0 * cpu ) )
67             # We measure at the server because it doesn't include
68             # the client's buffer fill rate
69             popen = server.popen( 'iperf -yc -s -p 5001' )
70             waitListening( client, server, 5001 )
71             # ignore empty result from waitListening/telnet
72             popen.stdout.readline()
73             client.cmd( 'iperf -yc -t %s -c %s' % ( seconds, server.IP() ) )
74             result = decode( popen.stdout.readline() ).split( ',' )
75             bps = float( result[ -1 ] )
76             popen.terminate()
77             net.stop()
78             updated = results.get( sched, [] )
79             updated += [ ( cpu, bps ) ]
80             results[ sched ] = updated
81
82     return results
83
84
85 def dump( results ):
86     "Dump results"
87
88     fmt = '%s\t%s\t%s\n'
89
90     info( '\n' )
91     info( fmt % ( 'sched', 'cpu', 'received bits/sec' ) )
92
93     for sched in sorted( results.keys() ):
94         entries = results[ sched ]
95         for cpu, bps in entries:
96             pct = '%d%%' % ( cpu * 100 )
97             mbps = '%.2e' % bps
98             info( fmt % ( sched, pct, mbps ) )
99
100
101 if __name__ == '__main__':
102     setLogLevel( 'info' )
103     # These are the limits for the hosts/iperfs - the
104     # rest is for system processes
105     limits = [ .5, .4, .3, .2, .1 ]
106     out = bwtest( limits )
107     dump( out )