summary.py 6.65 KB
Newer Older
1
2
3
4
#!/usr/bin/env python3
# -*- coding:utf-8 -*-

import time
Mario Hock's avatar
Mario Hock committed
5
import os
6
from itertools import zip_longest
Mario Hock's avatar
Mario Hock committed
7
8

from cnl_library import CNLParser
9
from split_text import split_proprtionally
10
11
12
13
14
15
16
17
18
19

## some "constants"/preferences
divisor = 1000000.0
rounding_digits = 2
unit = "MBits"


def format_timestamp(t):
    return time.strftime("%Y-%m-%d_%H:%M:%S", time.localtime(t))

20
21
22
23
24
25
26

def sprint_bold(text):
    return "\033[1m" + text + "\033[0m"

def sprint_inverted(text):
    return "\033[7m" + text + "\033[0m"

27
def print_inverted(text, **kwargs):
28
29
30
31
32
33
34
    #print( "\033[7m" + text + "\033[0m", **kwargs )
    print( sprint_inverted(text), **kwargs )


def print_in_two_columns(format_str, left_col, right_col):
    for l, r in zip_longest(left_col, right_col, fillvalue=""):
        print( format_str.format(l, r) )
35
36


37

Mario Hock's avatar
Mario Hock committed
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
def show_match(left_file, right_file):
    """
    Displays a brief summary of two CNL-file next to each other.

    Should be used with two files that belong to the same experiment
    (e.g. sender and receiver).
    """

    left_head, left_rates = left_file.as_column()
    right_head, right_rates = right_file.as_column()

    ## Head
    print_in_two_columns("{:<50} {}", left_head, right_head)

    ## Rates
    print_in_two_columns("{:<58} {}", left_rates, right_rates)
    #  Note: The escape sequence for the "rate-bar" is counted as characters.. :-/

    print()




61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
class LogAnalyzer:

    def __init__(self, cnl_file):
        self.cnl_file = cnl_file

        ## Get all fields to watch for activity (NIC, send and receive)
        self.nics = cnl_file.get_nics()
        self.watch_fields = list()
        nic_fields = [".send", ".receive"]
        for nic_name in self.nics:
            for nic_field in nic_fields:
                self.watch_fields.append( nic_name + nic_field )

        # important csv indices
        self.watch_indices = cnl_file.get_csv_indices_of(self.watch_fields)
        self.begin_index = cnl_file.get_csv_index_of("begin")
        self.end_index = cnl_file.get_csv_index_of("end")
Mario Hock's avatar
Mario Hock committed
78
        self.duration_index = cnl_file.get_csv_index_of("duration")
79
80
81
82
83
84
85
86
87
88


        ## Result variables
        self.experiment_start_time = None
        self.experiment_end_time = None
        self.recording_start_time = None
        self.recording_end_time = None

        self.sums = [0.0] * len(self.watch_fields)

Mario Hock's avatar
Mario Hock committed
89
90
91
        ## Trigger "summarize"
        self._summarize()

92
93
94
95
96
97
98
99
100
101

    def _is_activity(self, line):
        for field_name in self.watch_indices:
            if ( float( line[field_name] ) > 0 ):
                return True

        return False

    def _sum_line(self, line):
        for i in range( len(self.sums) ):
Mario Hock's avatar
Mario Hock committed
102
            self.sums[i] += line[ self.watch_indices[i] ] * line[self.duration_index]
103
104
105
106
107
108
109
110
111
112



    def _get_begin(self, line):
        return line[self.begin_index]

    def _get_end(self, line):
        return line[self.end_index]


Mario Hock's avatar
Mario Hock committed
113
    def _summarize(self):
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132

        for line in self.cnl_file.get_csv_iterator():
            ## on active samples
            if ( self._is_activity(line) ):

                # Find begin of the experiment.
                if ( not self.experiment_start_time ):
                    self.experiment_start_time = self._get_begin(line)

                # Find end of the experiment.
                self.experiment_end_time = self._get_end(line)

            ## Sum watched columns.
            self._sum_line(line)


        self.experiment_duration = self.experiment_end_time - self.experiment_start_time


Mario Hock's avatar
Mario Hock committed
133

134
    def show(self):
Mario Hock's avatar
Mario Hock committed
135
136
137
138
139
140
141
        print("=== Summary ===")
        #print( "Filename: " + os.path.relpath(self.cnl_file.filename) )
        form_str = "{:<10} {}"
        print( form_str.format("Filename:", os.path.basename(self.cnl_file.filename)) )
        print( form_str.format("Comment:", self.cnl_file.get_comment()) )
        print( form_str.format("Hostname:", self.cnl_file.get_sysinfo()["hostname"]) )
        print( form_str.format("Kernel:", self.cnl_file.get_sysinfo()["kernel"]) )
142
143
        print()

Mario Hock's avatar
Mario Hock committed
144
145
146
        print( form_str.format( "Start:", format_timestamp(self.experiment_start_time) ) )
        print( form_str.format( "End:", format_timestamp(self.experiment_end_time) ) )
        print( form_str.format( "Duration:", round(self.experiment_duration) ) )
147
148
        print()

Mario Hock's avatar
Mario Hock committed
149
150
        print( "CPUs: " + ", ".join(self.cnl_file.get_cpus()) )
        print( "NICs: " + ", ".join(self.cnl_file.get_nics()) )
151
152
153
        print()

        # Show average transmission rates.
Mario Hock's avatar
Mario Hock committed
154
        print("== Average transmission rates ==")
155
156
        for i in range( len(self.sums) ):
            speed = round(self.sums[i] / divisor / self.experiment_duration, rounding_digits)
Mario Hock's avatar
Mario Hock committed
157
            print( "{:<13} {:>10} {}/s".format(self.watch_fields[i]+":", speed, unit) )
158
159


Mario Hock's avatar
Mario Hock committed
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
    def show_brief(self):
        speeds = list()
        for i in range( len(self.sums) ):
            speed = "{:.2f}".format( round(self.sums[i] / divisor / self.experiment_duration, rounding_digits) )
            speeds.append( "{:>8} {}/s".format(speed, unit) )

        speeds_str = " ".join(speeds)
        filename = os.path.basename(self.cnl_file.filename)
        comments = self.cnl_file.get_comment().split(";")

        print( "{:<32} {}".format( filename + ":", speeds_str) )
        for comment in comments:
            print( "{:<32} {}".format( "", comment.strip()) )



Mario Hock's avatar
Mario Hock committed
176
177
178
179
180
181
182
    def as_column(self):
        ## TODO change name?

        ## Head

        head = list()

183
184
185
        filename = os.path.basename(self.cnl_file.filename)
        comments = self.cnl_file.get_comment().split(";")

Mario Hock's avatar
Mario Hock committed
186
        head.append( filename )
187
        for comment in comments:
Mario Hock's avatar
Mario Hock committed
188
            head.append(comment.strip()[:48])
189
190


Mario Hock's avatar
Mario Hock committed
191
192
193
        ## Transmission rates

        rates = list()
194
195
196
        for i in range( len(self.sums) ):
            speed = self.sums[i] / self.experiment_duration

197
198
199
200
201
202
203
204
            number_str = "{:.2f}".format( round(speed / divisor, rounding_digits) )
            bar_str = "{:<20}".format(number_str + " " + unit + "/s")

            label = "{:<6}".format( self.nics[int(i/2)] + ":" if i%2==0 else "" )

            parts = split_proprtionally(bar_str, [speed, 1000000*10000-speed])
            text = label + "|" + sprint_inverted(parts[0]) + parts[1] + "|"

Mario Hock's avatar
Mario Hock committed
205
206
207
208
            rates.append( text )

        return head, rates

209
210


Mario Hock's avatar
Mario Hock committed
211
212
213
214
    def visualize_brief(self):
        head, rates = self.as_column()

        print_in_two_columns("{:<50} {}", head, rates )
215
216


217
218
219
220
221

## MAIN ##
if __name__ == "__main__":
    import sys

Mario Hock's avatar
Mario Hock committed
222
    filenames = sorted( sys.argv[1:] )
223

Mario Hock's avatar
Mario Hock committed
224
225
226
    for filename in filenames:
        ## * Parse input file. *
        cnl_file = CNLParser(filename)
227

Mario Hock's avatar
Mario Hock committed
228
        log = LogAnalyzer(cnl_file)
Mario Hock's avatar
Mario Hock committed
229
        #log.summarize()
230

Mario Hock's avatar
Mario Hock committed
231
        if ( len(filenames) > 1 ):
232
233
            #log.show_brief()
            log.visualize_brief()
Mario Hock's avatar
Mario Hock committed
234
235
236
            print()
        else:
            log.show()