1#! /usr/bin/env python3
2#
3# Copyright 2007 Google Inc.
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; either version 2
8# of the License, or (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301,
18# USA.
19#
20"""Statistics gathering for the distcc-pump include server."""
21
22__author__ = "Nils Klarlund"
23
24import time
25
26resolve_expr_counter = 0 # number of computed includes
27master_hit_counter = 0 # summary node hits
28master_miss_counter = 0 # summary node misses
29resolve_counter = 0 # calls of Resolve method
30search_counter = 0 # number of probes in directory lists
31build_stat_counter = 0 # number of stats in build_stat_cache
32sys_stat_counter = 0 # number of calls to OS stat
33translation_unit_counter = 0 # number of translation units
34
35start_time = None
36translation_unit_time = None
37min_time = float('Inf')
38max_time = 0.0
39total_time = 0.0
40
41parse_file_total_time = 0.0
42parse_file_counter = 0 # number of files parsed
43
44parse_file_counter_last = 0 # the number of files parsed after previous
45                            # translation unit
46
47quote_path_total = 0 # total length of quote directory lists
48angle_path_total = 0 # total length of angle directory lists
49
50len_calculated_closure = 0 # number of all included files
51len_calculated_closure_nonsys =  0 # same, but excluding system files
52                                   # known to compiler
53len_exact_closure = 0 # number of all files in CPP-calculated closure
54len_surplus_nonsys = 0  # the difference between
55                        # len_calculated_closure and number of files
56                        # in exact closure that are not known to compiler
57
58find_node_counter = 0 # number of times FindNode is called
59
60
61def StartTiming():
62  global start_time, translation_unit_counter
63  """Mark the start of a request to find an include closure."""
64  translation_unit_counter += 1
65  start_time = time.perf_counter()
66
67
68def EndTiming():
69  """Mark the end of an include closure calculation."""
70  global translation_unit_time, min_time, max_time, total_time
71  translation_unit_time = time.perf_counter() - start_time
72  min_time = min(translation_unit_time, min_time)
73  max_time = max(translation_unit_time, max_time)
74  total_time += translation_unit_time
75
76
77def PrintStatistics(include_analyzer):
78    # Avoid division by zero in non-interesting case.
79    if translation_unit_counter == 0: return
80
81    print("TRANSLATION_UNIT: %s" % include_analyzer.translation_unit)
82    print (("TIME:    last %-2.3fs, min %-2.3fs, "
83            "max %-2.3fs, average %-2.3fs, #: %5d, total: %5.1fs") %
84           (translation_unit_time, min_time, max_time,
85            total_time/translation_unit_counter,
86            translation_unit_counter, total_time))
87    print ("PARSING: total %-5.3fs, total count: %4d, new files: %-5d" %
88           (parse_file_total_time, parse_file_counter,
89            parse_file_counter - parse_file_counter_last))
90    print("COUNTER: resolve_expr_counter:      %8d" % resolve_expr_counter)
91    print("COUNTER: master_hit_counter:        %8d" % master_hit_counter)
92    print("COUNTER: master_miss_counter:       %8d" % master_miss_counter)
93    print("SIZE:    master_cache               %8d" % (
94      len(include_analyzer.master_cache)))
95    print("COUNTER: sys_stat_counter:        %10d"  % sys_stat_counter)
96    print("COUNTER: build_stat_counter:      %10d" % build_stat_counter)
97    if resolve_counter != 0:
98      print("COUNTER: search_counter (average):      %4.1f" % (
99        float(search_counter)/resolve_counter))
100    print("SIZE:    include_dir_pairs:         %8d" % (
101      len(include_analyzer.include_dir_pairs)))
102    if 'quote_dirs' in include_analyzer.__dict__:
103        print("SIZE:    quote_path                 %8d" % (
104          len(include_analyzer.quote_dirs)))
105    if 'angle_dirs' in include_analyzer.__dict__:
106        print("SIZE:    angle_path                 %8d" % (
107          len(include_analyzer.angle_dirs)))
108    print("SIZE:    quote_path (average)           %4.1f" % (
109      float(quote_path_total)/translation_unit_counter))
110    print("SIZE:    angle_path (average)           %4.1f" % (
111      float(angle_path_total)/translation_unit_counter))
112    print("SIZE:    quote_dirs_set             %8d" % (
113      len(include_analyzer.quote_dirs_set)))
114    print("SIZE:    angle_dirs_set:            %8d" % (
115      len(include_analyzer.angle_dirs_set)))
116    print()
117    print("SIZE:    calculated_closure:        %8d" % len_calculated_closure)
118    print("SIZE:    calculated_closure_nonsys: %8d" % (
119      len_calculated_closure_nonsys))
120    print("SIZE:    exact_closure              %8d" % len_exact_closure)
121    print("SIZE:    surplus_nonsys             %8d" % len_surplus_nonsys)
122    print()
123