]>
Commit | Line | Data |
---|---|---|
7c673cae FG |
1 | /* |
2 | * Copyright 2005, 2016. Rene Rivera | |
3 | * Distributed under the Boost Software License, Version 1.0. | |
1e59de90 TL |
4 | * (See accompanying file LICENSE.txt or copy at |
5 | * https://www.bfgroup.xyz/b2/LICENSE.txt) | |
7c673cae FG |
6 | */ |
7 | ||
8 | #include "jam.h" | |
9 | #include "debug.h" | |
10 | #include "output.h" | |
11 | #include "hash.h" | |
12 | #include <time.h> | |
13 | ||
14 | ||
15 | static profile_frame * profile_stack = 0; | |
16 | static struct hash * profile_hash = 0; | |
17 | static profile_info profile_other = { 0 }; | |
18 | static profile_info profile_total = { 0 }; | |
19 | ||
20 | ||
21 | profile_frame * profile_init( OBJECT * rulename, profile_frame * frame ) | |
22 | { | |
23 | if ( DEBUG_PROFILE ) profile_enter( rulename, frame ); | |
24 | return frame; | |
25 | } | |
26 | ||
27 | ||
28 | void profile_enter( OBJECT * rulename, profile_frame * frame ) | |
29 | { | |
30 | if ( DEBUG_PROFILE ) | |
31 | { | |
32 | double start = profile_clock(); | |
33 | profile_info * p; | |
34 | ||
35 | if ( !profile_hash && rulename ) | |
36 | profile_hash = hashinit( sizeof( profile_info ), "profile" ); | |
37 | ||
38 | if ( rulename ) | |
39 | { | |
40 | int found; | |
41 | p = (profile_info *)hash_insert( profile_hash, rulename, &found ); | |
42 | if ( !found ) | |
43 | { | |
44 | p->name = rulename; | |
45 | p->cumulative = 0; | |
46 | p->net = 0; | |
47 | p->num_entries = 0; | |
48 | p->stack_count = 0; | |
49 | p->memory = 0; | |
50 | } | |
51 | } | |
52 | else | |
53 | { | |
54 | p = &profile_other; | |
55 | } | |
56 | ||
57 | p->num_entries += 1; | |
58 | p->stack_count += 1; | |
59 | ||
60 | frame->info = p; | |
61 | ||
62 | frame->caller = profile_stack; | |
63 | profile_stack = frame; | |
64 | ||
65 | frame->entry_time = profile_clock(); | |
66 | frame->overhead = 0; | |
67 | frame->subrules = 0; | |
68 | ||
69 | /* caller pays for the time it takes to play with the hash table */ | |
70 | if ( frame->caller ) | |
71 | frame->caller->overhead += frame->entry_time - start; | |
72 | } | |
73 | } | |
74 | ||
75 | ||
1e59de90 | 76 | void profile_memory( size_t mem ) |
7c673cae FG |
77 | { |
78 | if ( DEBUG_PROFILE ) | |
79 | if ( profile_stack && profile_stack->info ) | |
80 | profile_stack->info->memory += ((double)mem) / 1024; | |
81 | } | |
82 | ||
83 | ||
84 | void profile_exit( profile_frame * frame ) | |
85 | { | |
86 | if ( DEBUG_PROFILE ) | |
87 | { | |
88 | /* Cumulative time for this call. */ | |
89 | double t = profile_clock() - frame->entry_time - frame->overhead; | |
90 | /* If this rule is already present on the stack, do not add the time for | |
91 | * this instance. | |
92 | */ | |
93 | if ( frame->info->stack_count == 1 ) | |
94 | frame->info->cumulative += t; | |
92f5a8d4 | 95 | /* Net time does not depend on presence of the same rule in call stack. |
7c673cae FG |
96 | */ |
97 | frame->info->net += t - frame->subrules; | |
98 | ||
99 | if ( frame->caller ) | |
100 | { | |
101 | /* Caller's cumulative time must account for this overhead. */ | |
102 | frame->caller->overhead += frame->overhead; | |
103 | frame->caller->subrules += t; | |
104 | } | |
105 | /* Pop this stack frame. */ | |
106 | --frame->info->stack_count; | |
107 | profile_stack = frame->caller; | |
108 | } | |
109 | } | |
110 | ||
111 | ||
112 | static void dump_profile_entry( void * p_, void * ignored ) | |
113 | { | |
114 | profile_info * p = (profile_info *)p_; | |
115 | double mem_each = ( p->memory / ( p->num_entries ? p->num_entries : 1 | |
116 | ) ); | |
117 | double q = p->net; | |
118 | if (p->num_entries) q /= p->num_entries; | |
119 | if ( !ignored ) | |
120 | { | |
121 | profile_total.cumulative += p->net; | |
122 | profile_total.memory += p->memory; | |
123 | } | |
124 | out_printf( "%10ld %12.6f %12.6f %12.8f %10.2f %10.2f %s\n", p->num_entries, | |
125 | p->cumulative, p->net, q, p->memory, mem_each, object_str( p->name ) ); | |
126 | } | |
127 | ||
128 | ||
129 | void profile_dump() | |
130 | { | |
131 | if ( profile_hash ) | |
132 | { | |
133 | out_printf( "%10s %12s %12s %12s %10s %10s %s\n", "--count--", "--gross--", | |
134 | "--net--", "--each--", "--mem--", "--each--", "--name--" ); | |
135 | hashenumerate( profile_hash, dump_profile_entry, 0 ); | |
136 | profile_other.name = constant_other; | |
137 | dump_profile_entry( &profile_other, 0 ); | |
138 | profile_total.name = constant_total; | |
139 | dump_profile_entry( &profile_total, (void *)1 ); | |
140 | } | |
141 | } | |
142 | ||
143 | double profile_clock() | |
144 | { | |
145 | return ((double) clock()) / CLOCKS_PER_SEC; | |
146 | } | |
147 | ||
148 | OBJECT * profile_make_local( char const * scope ) | |
149 | { | |
150 | if ( DEBUG_PROFILE ) | |
151 | { | |
152 | return object_new( scope ); | |
153 | } | |
154 | else | |
155 | { | |
156 | return 0; | |
157 | } | |
158 | } |