2 * Copyright 2005, 2016. Rene Rivera
3 * Distributed under the Boost Software License, Version 1.0.
4 * (See accompanying file LICENSE_1_0.txt or copy at
5 * http://www.boost.org/LICENSE_1_0.txt)
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 };
21 profile_frame
* profile_init( OBJECT
* rulename
, profile_frame
* frame
)
23 if ( DEBUG_PROFILE
) profile_enter( rulename
, frame
);
28 void profile_enter( OBJECT
* rulename
, profile_frame
* frame
)
32 double start
= profile_clock();
35 if ( !profile_hash
&& rulename
)
36 profile_hash
= hashinit( sizeof( profile_info
), "profile" );
41 p
= (profile_info
*)hash_insert( profile_hash
, rulename
, &found
);
62 frame
->caller
= profile_stack
;
63 profile_stack
= frame
;
65 frame
->entry_time
= profile_clock();
69 /* caller pays for the time it takes to play with the hash table */
71 frame
->caller
->overhead
+= frame
->entry_time
- start
;
76 void profile_memory( long mem
)
79 if ( profile_stack
&& profile_stack
->info
)
80 profile_stack
->info
->memory
+= ((double)mem
) / 1024;
84 void profile_exit( profile_frame
* frame
)
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
93 if ( frame
->info
->stack_count
== 1 )
94 frame
->info
->cumulative
+= t
;
95 /* Net time does not depend on presense of the same rule in call stack.
97 frame
->info
->net
+= t
- frame
->subrules
;
101 /* Caller's cumulative time must account for this overhead. */
102 frame
->caller
->overhead
+= frame
->overhead
;
103 frame
->caller
->subrules
+= t
;
105 /* Pop this stack frame. */
106 --frame
->info
->stack_count
;
107 profile_stack
= frame
->caller
;
112 static void dump_profile_entry( void * p_
, void * ignored
)
114 profile_info
* p
= (profile_info
*)p_
;
115 double mem_each
= ( p
->memory
/ ( p
->num_entries
? p
->num_entries
: 1
118 if (p
->num_entries
) q
/= p
->num_entries
;
121 profile_total
.cumulative
+= p
->net
;
122 profile_total
.memory
+= p
->memory
;
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
) );
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 );
143 double profile_clock()
145 return ((double) clock()) / CLOCKS_PER_SEC
;
148 OBJECT
* profile_make_local( char const * scope
)
152 return object_new( scope
);