Merge lp:~prafulla-t/drizzle/drz-fast-timer-and-time-profile-refactoring into lp:~drizzle-trunk/drizzle/development
- drz-fast-timer-and-time-profile-refactoring
- Merge into development
Status: | Rejected |
---|---|
Rejected by: | Lee Bieber |
Proposed branch: | lp:~prafulla-t/drizzle/drz-fast-timer-and-time-profile-refactoring |
Merge into: | lp:~drizzle-trunk/drizzle/development |
Diff against target: |
1013 lines (+693/-16) 9 files modified
drizzled/drizzled.cc (+0/-1) drizzled/filesort.cc (+35/-8) drizzled/include.am (+1/-0) drizzled/optimizer/range.cc (+2/-0) drizzled/session.cc (+7/-2) drizzled/session.h (+21/-2) drizzled/sql_parse.cc (+13/-1) drizzled/sql_select.cc (+0/-2) drizzled/time_profile.h (+614/-0) |
To merge this branch: | bzr merge lp:~prafulla-t/drizzle/drz-fast-timer-and-time-profile-refactoring |
Related bugs: | |
Related blueprints: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Stewart Smith (community) | Disapprove | ||
Monty Taylor | Pending | ||
Brian Aker | Pending | ||
Review via email: mp+32887@code.launchpad.net |
Commit message
Description of the change
Hi
This is first attempt to have timer classes and easy macros
for doing time-related profiling of drizzle code.
We have three choice for timer classes.
rtdtc based timer
clock_gettime based timer
gettimeofday based timer.
As an example of how macros can be used, I have added few timer(uSec precision) profile related macros around filesort code.
Here what is dumped in error stream once query/command execution is done.
-------
Command : create table t(c1 int)
query
{
mysql_parse, acc= 71303 microsec, occ=1
}
-------
-------
Command : select * from t
query
{
mysql_parse, acc= 630 microsec, occ=1
}
-------
-------
Command : select * from t order by 1
query
{
mysql_parse, acc= 365 microsec, occ=1
}
filesort
{
estimateRowsUpp
filesort, acc= 95 microsec, occ=1
find_all_keys, acc= 49 microsec, occ=1
innodb:
raw_read, acc= 28 microsec, occ=1
register_
save_index, acc= 2 microsec, occ=1
}
-------
acc = accumulated time
occ = number of timers timer code was invoked.
In order to enable time profiling, we need to turn on TIME_PROFILE
macro in time_profile.h
I hope this would be helpful in profiling various part of drizzle code.
Could you please go over the code and suggest improvement if any ?
PrafullaT (prafulla-t) wrote : | # |
Monty Taylor (mordred) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 08/17/2010 08:18 AM, Prafulla Tekawade wrote:
> Prafulla Tekawade has proposed merging lp:~prafulla-tekawade/drizzle/drz-fast-timer-and-time-profile-refactoring into lp:drizzle.
>
> Requested reviews:
> Drizzle Merge Team (drizzle-merge)
>
>
> Hi
> This is first attempt to have timer classes and easy macros
> for doing time-related profiling of drizzle code.
This looks very potentially useful.
> We have three choice for timer classes.
> rtdtc based timer
> clock_gettime based timer
> gettimeofday based timer.
Could you also investigate Boost::DateTime and see if it's a useful
choice for timer class implementation? I'm looking at using it for some
other things as well and I'd love it if we could have one set of
time-related code.
However, if it's not suitable, that's fine.
> As an example of how macros can be used, I have added few timer(uSec precision) profile related macros around filesort code.
>
> Here what is dumped in error stream once query/command execution is done.
>
> -------
> query
> {
> mysql_parse, acc= 366639 microsec, occ=1
> }
>
> filesort
> {
> estimateRowsUpp
> filesort, acc= 262365 microsec, occ=1
> find_all_keys, acc= 227612 microsec, occ=1
> innodb:
> make_char_array, acc= 18 microsec, occ=1
> optimizer:
> raw_read, acc= 68733 microsec, occ=12011
> write_keys, acc= 46767 microsec, occ=12010
> }
>
> acc = accumulated time
> occ = number of timers timer code was invoked.
>
> In order to enable time profiling, we need to turn on TIME_PROFILE
> macro in time_profile.h
>
> I hope this would be helpful in profiling various part of drizzle code.
> Could you please go over the code and suggest improvement if any ?
>
A few quick notes...
Please do not include config.h in drizzled/
included by any .cc files that use it.
For the output - would you see if it's possible to hook in to the error
message infrastructure? (errmsg_printf and friends) - that way it's
conceivable that someone could use profiling in an infrastructure where
server messages are reported to a centralized server. Like
boost::datetime, it's possible this won't work well yet - I've been
meaning to add a stream-like interface to that system and just haven't
gotten there yet.
Other than that it looks reasonable (I haven't walked through the actual
timer impl code fully yet.)
Monty
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkx
n7IAoO7Yr/
=UPvq
-----END PGP SIGNATURE-----
- 1701. By PrafullaT
-
Time profiling related macros were misplaced due to
wrong patch in filesort.cc
Putting them at right place now. - 1702. By PrafullaT
-
Merge from mainline branch.
- 1703. By PrafullaT
-
o. Adding some printf which prints command along with profile data
This would help associating profiling data with input command
easily
o. Removing some unnecessary printfs in mysql_parse method
o. Replaced fprintf with errmsg_printf as suggested by Monty in review
o. Adding license information
o. Adding guards around use clock_gettime method as it may not
available on some platform. - 1704. By PrafullaT
-
Fixing some formatting issues.
- 1705. By PrafullaT
-
Some more formatting issues.
Brian Aker (brianaker) wrote : | # |
Hi!
A couple of things:
1) We want to avoid using pthread_key_t because it ties sessions to threads, and we want sessions to float between threads.
2) At the beginning of each query we call gettimeofday() in Session. You can base any calls you need off of that initially.
3) The style in the code is off from our coding style.
How can we provide this data to a user? Have you thought about providing a table function to display it for the last query?
Cheers,
-Brian
(BTW I will be offline for an extended period of time starting this weekend, so I will be slow to respond for the next two weeks).
PrafullaT (prafulla-t) wrote : | # |
Hi,
Thanks for review Brian.
> Hi!
>
> A couple of things:
>
> 1) We want to avoid using pthread_key_t because it ties sessions to threads,
> and we want sessions to float between threads.
I see , I wanted profile code to be done for a single thread to avoid having
thread related complexity(mutex etc) in profiling code.
Do you suggest creating independent pthread_key_t for ThreadProfile ?
That was my original plan but then I saw sessions are created per thread so I hung
threadprofile object pointer off that class.
> 2) At the beginning of each query we call gettimeofday() in Session. You can
> base any calls you need off of that initially.
>
> 3) The style in the code is off from our coding style.
I will work on the style.
>
> How can we provide this data to a user? Have you thought about providing a
> table function to display it for the last query?
User ?
I thought this would be useful for developer working on drizzle code as profiling
related code will most probably have names of internal function etc.
But yes, the data can be made available to use through some user variable.
I'll think about this.
--
Thanks
Prafulla
Brian Aker (brianaker) wrote : | # |
hi!
Please ask monty (or Lee) to set you up with hudson param build to see how this patch does with performance regression on the benchmarks.
Cheers,
-Brian
Monty Taylor (mordred) wrote : | # |
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1
On 08/20/2010 09:30 PM, Brian Aker wrote:
> hi!
>
> Please ask monty (or Lee) to set you up with hudson param build to see how this patch does with performance regression on the benchmarks.
Make yourself a user account on http://
me what it is.
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.4.10 (GNU/Linux)
Comment: Using GnuPG with Mozilla - http://
iEYEARECAAYFAkx
PWcAoOJcCCt95Ci
=pk3X
-----END PGP SIGNATURE-----
PrafullaT (prafulla-t) wrote : | # |
Hi,
> Please ask monty (or Lee) to set you up with hudson param build to see how
> this patch does with performance regression on the benchmarks.
I ran few sysbench related test to see how it performs with this patch
Here are results.
With time profiling default on
https:/
Without time profiling default off
https:/
Performance becomes pretty bad with this time profiling default on.
This should be due to err_msgprintf which is used to print profile
output along with input command string.
I wrote this patch as an aid to developer working on performance
intensive project, to see which part of code is taking what time
etc. I do not think, this should be default on. We can however make user
timer to get timing information. Developer working
on performance related projects, should turn it on themselves. (Maybe
./configure can be modified to take extra param for this).
Let me know what you think
--
Thanks
Prafulla
Brian Aker (brianaker) wrote : | # |
(I am on vacation for the next two weeks, so my resonces will be slow).
If we don't print but only collect timing information, how does it effect performance ?
PrafullaT (prafulla-t) wrote : | # |
> If we don't print but only collect timing information, how does it effect
> performance ?
If we have TIME_PROFILE_ON define'ed, it collects timing information as well as
prints it at the end of query execution using errmsg_printf,
This printing is what should be causing performance degradation.
In current branch TIME_PROFILE_ON is off by default, and hence performance
is pretty much within norm.
--
Thanks
Prauflla
PrafullaT (prafulla-t) wrote : | # |
> > If we don't print but only collect timing information, how does it effect
> > performance ?
I just ran tests without printing code and TIME_PROFILE_ON defin'ed
https:/
https:/
Performance is worse with this settings too.
I need to check root cause of these regression.
--
Thanks
Prafulla
Stewart Smith (stewart) wrote : | # |
The regression is because any call getting a timer is relatively expensive. Also, when you have inline asm somewhere, it does limit what the compiler can do to optimise (think about instruction re-ordering around the getting of the timer).
I'd much prefer to see something based on the Linux perf-events infrastructure instead - it could be easily used to get a much better profile of what's going on instead of just what we think would ever be a bottleneck.
I guess you could hook into dtrace on OSX/Solaris but I don't think anybody really cares :)
Stewart Smith (stewart) wrote : | # |
(that being said, for an implementation of this type of timers, this look relatively okay... I just disagree with the approach)
Unmerged revisions
- 1713. By PrafullaT
-
Fixing build failure
- 1712. By PrafullaT
-
Disabling just printing of profiling code, to see
impact of priniting on performance. - 1711. By PrafullaT
-
Some more changes for coding standard
- 1710. By PrafullaT
-
Making some changes to match up to drizzled coding standard
- 1709. By PrafullaT
-
Merge from trunk
- 1708. By PrafullaT
-
Chaning profiling to default off
- 1707. By PrafullaT
-
Fixing build failure on x86 machines
Also adding time_profile.h to include.am - 1706. By PrafullaT
-
Merge from trunk
- 1705. By PrafullaT
-
Some more formatting issues.
- 1704. By PrafullaT
-
Fixing some formatting issues.
Preview Diff
1 | === modified file 'drizzled/drizzled.cc' | |||
2 | --- drizzled/drizzled.cc 2010-08-24 01:36:17 +0000 | |||
3 | +++ drizzled/drizzled.cc 2010-08-26 04:32:43 +0000 | |||
4 | @@ -338,7 +338,6 @@ | |||
5 | 338 | boost::mutex LOCK_open; | 338 | boost::mutex LOCK_open; |
6 | 339 | boost::mutex LOCK_global_system_variables; | 339 | boost::mutex LOCK_global_system_variables; |
7 | 340 | boost::mutex LOCK_thread_count; | 340 | boost::mutex LOCK_thread_count; |
8 | 341 | |||
9 | 342 | boost::condition_variable COND_refresh; | 341 | boost::condition_variable COND_refresh; |
10 | 343 | boost::condition_variable COND_thread_count; | 342 | boost::condition_variable COND_thread_count; |
11 | 344 | pthread_t signal_thread; | 343 | pthread_t signal_thread; |
12 | 345 | 344 | ||
13 | === modified file 'drizzled/filesort.cc' | |||
14 | --- drizzled/filesort.cc 2010-08-17 01:34:55 +0000 | |||
15 | +++ drizzled/filesort.cc 2010-08-26 04:32:43 +0000 | |||
16 | @@ -41,6 +41,8 @@ | |||
17 | 41 | #include "drizzled/internal/my_sys.h" | 41 | #include "drizzled/internal/my_sys.h" |
18 | 42 | #include "plugin/myisam/myisam.h" | 42 | #include "plugin/myisam/myisam.h" |
19 | 43 | #include "drizzled/plugin/transactional_storage_engine.h" | 43 | #include "drizzled/plugin/transactional_storage_engine.h" |
20 | 44 | #include "drizzled/time_profile.h" | ||
21 | 45 | |||
22 | 44 | 46 | ||
23 | 45 | using namespace std; | 47 | using namespace std; |
24 | 46 | 48 | ||
25 | @@ -135,6 +137,8 @@ | |||
26 | 135 | optimizer::SqlSelect *select, ha_rows max_rows, | 137 | optimizer::SqlSelect *select, ha_rows max_rows, |
27 | 136 | bool sort_positions, ha_rows *examined_rows) | 138 | bool sort_positions, ha_rows *examined_rows) |
28 | 137 | { | 139 | { |
29 | 140 | START_PROFILING_PHASE("filesort", "microsec"); | ||
30 | 141 | BLOCK_MICRO_SEC_TIMER("filesort"); | ||
31 | 138 | int error; | 142 | int error; |
32 | 139 | uint32_t memavl, min_sort_memory; | 143 | uint32_t memavl, min_sort_memory; |
33 | 140 | uint32_t maxbuffer; | 144 | uint32_t maxbuffer; |
34 | @@ -151,11 +155,14 @@ | |||
35 | 151 | 155 | ||
36 | 152 | DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName()); | 156 | DRIZZLE_FILESORT_START(table->getShare()->getSchemaName(), table->getShare()->getTableName()); |
37 | 153 | 157 | ||
43 | 154 | /* | 158 | { |
44 | 155 | Release InnoDB's adaptive hash index latch (if holding) before | 159 | BLOCK_MICRO_SEC_TIMER("innodb::releaselatches"); |
45 | 156 | running a sort. | 160 | /* |
46 | 157 | */ | 161 | Release InnoDB's adaptive hash index latch (if holding) before |
47 | 158 | plugin::TransactionalStorageEngine::releaseTemporaryLatches(session); | 162 | running a sort. |
48 | 163 | */ | ||
49 | 164 | plugin::TransactionalStorageEngine::releaseTemporaryLatches(session); | ||
50 | 165 | } | ||
51 | 159 | 166 | ||
52 | 160 | /* | 167 | /* |
53 | 161 | Don't use table->sort in filesort as it is also used by | 168 | Don't use table->sort in filesort as it is also used by |
54 | @@ -226,6 +233,7 @@ | |||
55 | 226 | else | 233 | else |
56 | 227 | #endif | 234 | #endif |
57 | 228 | { | 235 | { |
58 | 236 | BLOCK_MICRO_SEC_TIMER("estimateRowsUpperBound"); | ||
59 | 229 | records= table->cursor->estimate_rows_upper_bound(); | 237 | records= table->cursor->estimate_rows_upper_bound(); |
60 | 230 | /* | 238 | /* |
61 | 231 | If number of records is not known, use as much of sort buffer | 239 | If number of records is not known, use as much of sort buffer |
62 | @@ -268,10 +276,12 @@ | |||
63 | 268 | param.keys--; /* TODO: check why we do this */ | 276 | param.keys--; /* TODO: check why we do this */ |
64 | 269 | param.sort_form= table; | 277 | param.sort_form= table; |
65 | 270 | param.end=(param.local_sortorder=sortorder)+s_length; | 278 | param.end=(param.local_sortorder=sortorder)+s_length; |
66 | 279 | |||
67 | 271 | if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers, | 280 | if ((records=find_all_keys(session, ¶m,select,sort_keys, &buffpek_pointers, |
70 | 272 | &tempfile, selected_records_file)) == | 281 | &tempfile, selected_records_file)) == HA_POS_ERROR) |
69 | 273 | HA_POS_ERROR) | ||
71 | 274 | goto err; | 282 | goto err; |
72 | 283 | |||
73 | 284 | |||
74 | 275 | maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek)); | 285 | maxbuffer= (uint32_t) (my_b_tell(&buffpek_pointers)/sizeof(*buffpek)); |
75 | 276 | 286 | ||
76 | 277 | if (maxbuffer == 0) // The whole set is in memory | 287 | if (maxbuffer == 0) // The whole set is in memory |
77 | @@ -363,7 +373,7 @@ | |||
78 | 363 | DRIZZLE_FILESORT_DONE(error, records); | 373 | DRIZZLE_FILESORT_DONE(error, records); |
79 | 364 | return (error ? HA_POS_ERROR : records); | 374 | return (error ? HA_POS_ERROR : records); |
80 | 365 | } /* filesort */ | 375 | } /* filesort */ |
82 | 366 | 376 | ||
83 | 367 | 377 | ||
84 | 368 | void Table::filesort_free_buffers(bool full) | 378 | void Table::filesort_free_buffers(bool full) |
85 | 369 | { | 379 | { |
86 | @@ -421,6 +431,8 @@ | |||
87 | 421 | static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count, | 431 | static unsigned char *read_buffpek_from_file(internal::IO_CACHE *buffpek_pointers, uint32_t count, |
88 | 422 | unsigned char *buf) | 432 | unsigned char *buf) |
89 | 423 | { | 433 | { |
90 | 434 | |||
91 | 435 | BLOCK_MICRO_SEC_TIMER("read_buffpek_from_file"); | ||
92 | 424 | uint32_t length= sizeof(buffpek_st)*count; | 436 | uint32_t length= sizeof(buffpek_st)*count; |
93 | 425 | unsigned char *tmp= buf; | 437 | unsigned char *tmp= buf; |
94 | 426 | if (count > UINT_MAX/sizeof(buffpek_st)) | 438 | if (count > UINT_MAX/sizeof(buffpek_st)) |
95 | @@ -484,6 +496,7 @@ | |||
96 | 484 | internal::IO_CACHE *buffpek_pointers, | 496 | internal::IO_CACHE *buffpek_pointers, |
97 | 485 | internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile) | 497 | internal::IO_CACHE *tempfile, internal::IO_CACHE *indexfile) |
98 | 486 | { | 498 | { |
99 | 499 | BLOCK_MICRO_SEC_TIMER("find_all_keys"); | ||
100 | 487 | int error,flag,quick_select; | 500 | int error,flag,quick_select; |
101 | 488 | uint32_t idx,indexpos,ref_length; | 501 | uint32_t idx,indexpos,ref_length; |
102 | 489 | unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; | 502 | unsigned char *ref_pos,*next_pos,ref_buff[MAX_REFLENGTH]; |
103 | @@ -540,6 +553,7 @@ | |||
104 | 540 | { | 553 | { |
105 | 541 | if (quick_select) | 554 | if (quick_select) |
106 | 542 | { | 555 | { |
107 | 556 | BLOCK_MICRO_SEC_TIMER("quick_select_read"); | ||
108 | 543 | if ((error= read_record_info.read_record(&read_record_info))) | 557 | if ((error= read_record_info.read_record(&read_record_info))) |
109 | 544 | { | 558 | { |
110 | 545 | error= HA_ERR_END_OF_FILE; | 559 | error= HA_ERR_END_OF_FILE; |
111 | @@ -551,6 +565,7 @@ | |||
112 | 551 | { | 565 | { |
113 | 552 | if (indexfile) | 566 | if (indexfile) |
114 | 553 | { | 567 | { |
115 | 568 | BLOCK_MICRO_SEC_TIMER("index_file_read"); | ||
116 | 554 | if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) | 569 | if (my_b_read(indexfile,(unsigned char*) ref_pos,ref_length)) |
117 | 555 | { | 570 | { |
118 | 556 | error= errno ? errno : -1; /* Abort */ | 571 | error= errno ? errno : -1; /* Abort */ |
119 | @@ -560,6 +575,7 @@ | |||
120 | 560 | } | 575 | } |
121 | 561 | else | 576 | else |
122 | 562 | { | 577 | { |
123 | 578 | BLOCK_MICRO_SEC_TIMER("raw_read"); | ||
124 | 563 | error=file->rnd_next(sort_form->getInsertRecord()); | 579 | error=file->rnd_next(sort_form->getInsertRecord()); |
125 | 564 | 580 | ||
126 | 565 | if (!flag) | 581 | if (!flag) |
127 | @@ -663,6 +679,7 @@ | |||
128 | 663 | write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count, | 679 | write_keys(SORTPARAM *param, register unsigned char **sort_keys, uint32_t count, |
129 | 664 | internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile) | 680 | internal::IO_CACHE *buffpek_pointers, internal::IO_CACHE *tempfile) |
130 | 665 | { | 681 | { |
131 | 682 | BLOCK_MICRO_SEC_TIMER("write_keys"); | ||
132 | 666 | size_t sort_length, rec_length; | 683 | size_t sort_length, rec_length; |
133 | 667 | unsigned char **end; | 684 | unsigned char **end; |
134 | 668 | buffpek_st buffpek; | 685 | buffpek_st buffpek; |
135 | @@ -699,6 +716,7 @@ | |||
136 | 699 | 716 | ||
137 | 700 | static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length) | 717 | static inline void store_length(unsigned char *to, uint32_t length, uint32_t pack_length) |
138 | 701 | { | 718 | { |
139 | 719 | BLOCK_MICRO_SEC_TIMER("store_length"); | ||
140 | 702 | switch (pack_length) { | 720 | switch (pack_length) { |
141 | 703 | case 1: | 721 | case 1: |
142 | 704 | *to= (unsigned char) length; | 722 | *to= (unsigned char) length; |
143 | @@ -721,6 +739,7 @@ | |||
144 | 721 | static void make_sortkey(register SORTPARAM *param, | 739 | static void make_sortkey(register SORTPARAM *param, |
145 | 722 | register unsigned char *to, unsigned char *ref_pos) | 740 | register unsigned char *to, unsigned char *ref_pos) |
146 | 723 | { | 741 | { |
147 | 742 | BLOCK_MICRO_SEC_TIMER("make_sortkey"); | ||
148 | 724 | Field *field; | 743 | Field *field; |
149 | 725 | SortField *sort_field; | 744 | SortField *sort_field; |
150 | 726 | size_t length; | 745 | size_t length; |
151 | @@ -954,6 +973,7 @@ | |||
152 | 954 | 973 | ||
153 | 955 | static void register_used_fields(SORTPARAM *param) | 974 | static void register_used_fields(SORTPARAM *param) |
154 | 956 | { | 975 | { |
155 | 976 | BLOCK_MICRO_SEC_TIMER("register_used_fields"); | ||
156 | 957 | SortField *sort_field; | 977 | SortField *sort_field; |
157 | 958 | Table *table=param->sort_form; | 978 | Table *table=param->sort_form; |
158 | 959 | 979 | ||
159 | @@ -992,6 +1012,7 @@ | |||
160 | 992 | static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, | 1012 | static bool save_index(SORTPARAM *param, unsigned char **sort_keys, uint32_t count, |
161 | 993 | filesort_info_st *table_sort) | 1013 | filesort_info_st *table_sort) |
162 | 994 | { | 1014 | { |
163 | 1015 | BLOCK_MICRO_SEC_TIMER("save_index"); | ||
164 | 995 | uint32_t offset,res_length; | 1016 | uint32_t offset,res_length; |
165 | 996 | unsigned char *to; | 1017 | unsigned char *to; |
166 | 997 | 1018 | ||
167 | @@ -1017,6 +1038,7 @@ | |||
168 | 1017 | int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer, | 1038 | int merge_many_buff(SORTPARAM *param, unsigned char *sort_buffer, |
169 | 1018 | buffpek_st *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file) | 1039 | buffpek_st *buffpek, uint32_t *maxbuffer, internal::IO_CACHE *t_file) |
170 | 1019 | { | 1040 | { |
171 | 1041 | BLOCK_MICRO_SEC_TIMER("merge_many_buf"); | ||
172 | 1020 | register uint32_t i; | 1042 | register uint32_t i; |
173 | 1021 | internal::IO_CACHE t_file2,*from_file,*to_file,*temp; | 1043 | internal::IO_CACHE t_file2,*from_file,*to_file,*temp; |
174 | 1022 | buffpek_st *lastbuff; | 1044 | buffpek_st *lastbuff; |
175 | @@ -1074,6 +1096,7 @@ | |||
176 | 1074 | uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek, | 1096 | uint32_t read_to_buffer(internal::IO_CACHE *fromfile, buffpek_st *buffpek, |
177 | 1075 | uint32_t rec_length) | 1097 | uint32_t rec_length) |
178 | 1076 | { | 1098 | { |
179 | 1099 | BLOCK_MICRO_SEC_TIMER("read_to_buffer"); | ||
180 | 1077 | register uint32_t count; | 1100 | register uint32_t count; |
181 | 1078 | uint32_t length; | 1101 | uint32_t length; |
182 | 1079 | 1102 | ||
183 | @@ -1130,6 +1153,7 @@ | |||
184 | 1130 | buffpek_st *lastbuff, buffpek_st *Fb, buffpek_st *Tb, | 1153 | buffpek_st *lastbuff, buffpek_st *Fb, buffpek_st *Tb, |
185 | 1131 | int flag) | 1154 | int flag) |
186 | 1132 | { | 1155 | { |
187 | 1156 | BLOCK_MICRO_SEC_TIMER("merge_buffers"); | ||
188 | 1133 | int error; | 1157 | int error; |
189 | 1134 | uint32_t rec_length,res_length,offset; | 1158 | uint32_t rec_length,res_length,offset; |
190 | 1135 | size_t sort_length; | 1159 | size_t sort_length; |
191 | @@ -1336,6 +1360,7 @@ | |||
192 | 1336 | buffpek_st *buffpek, uint32_t maxbuffer, | 1360 | buffpek_st *buffpek, uint32_t maxbuffer, |
193 | 1337 | internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile) | 1361 | internal::IO_CACHE *tempfile, internal::IO_CACHE *outfile) |
194 | 1338 | { | 1362 | { |
195 | 1363 | BLOCK_MICRO_SEC_TIMER("merge_index"); | ||
196 | 1339 | if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek, | 1364 | if (merge_buffers(param,tempfile,outfile,sort_buffer,buffpek,buffpek, |
197 | 1340 | buffpek+maxbuffer,1)) | 1365 | buffpek+maxbuffer,1)) |
198 | 1341 | return(1); | 1366 | return(1); |
199 | @@ -1570,6 +1595,7 @@ | |||
200 | 1570 | static void | 1595 | static void |
201 | 1571 | unpack_addon_fields(struct sort_addon_field_st *addon_field, unsigned char *buff) | 1596 | unpack_addon_fields(struct sort_addon_field_st *addon_field, unsigned char *buff) |
202 | 1572 | { | 1597 | { |
203 | 1598 | BLOCK_MICRO_SEC_TIMER("unpack_addon_fields"); | ||
204 | 1573 | Field *field; | 1599 | Field *field; |
205 | 1574 | sort_addon_field_st *addonf= addon_field; | 1600 | sort_addon_field_st *addonf= addon_field; |
206 | 1575 | 1601 | ||
207 | @@ -1594,6 +1620,7 @@ | |||
208 | 1594 | 1620 | ||
209 | 1595 | void change_double_for_sort(double nr,unsigned char *to) | 1621 | void change_double_for_sort(double nr,unsigned char *to) |
210 | 1596 | { | 1622 | { |
211 | 1623 | BLOCK_MICRO_SEC_TIMER("change_double_for_sort"); | ||
212 | 1597 | unsigned char *tmp=(unsigned char*) to; | 1624 | unsigned char *tmp=(unsigned char*) to; |
213 | 1598 | if (nr == 0.0) | 1625 | if (nr == 0.0) |
214 | 1599 | { /* Change to zero string */ | 1626 | { /* Change to zero string */ |
215 | 1600 | 1627 | ||
216 | === modified file 'drizzled/include.am' | |||
217 | --- drizzled/include.am 2010-08-20 18:39:24 +0000 | |||
218 | +++ drizzled/include.am 2010-08-26 04:32:43 +0000 | |||
219 | @@ -428,6 +428,7 @@ | |||
220 | 428 | drizzled/temporal_interval.h \ | 428 | drizzled/temporal_interval.h \ |
221 | 429 | drizzled/thr_lock.h \ | 429 | drizzled/thr_lock.h \ |
222 | 430 | drizzled/time_functions.h \ | 430 | drizzled/time_functions.h \ |
223 | 431 | drizzled/time_profile.h \ | ||
224 | 431 | drizzled/tmp_table_param.h \ | 432 | drizzled/tmp_table_param.h \ |
225 | 432 | drizzled/transaction_context.h \ | 433 | drizzled/transaction_context.h \ |
226 | 433 | drizzled/transaction_services.h \ | 434 | drizzled/transaction_services.h \ |
227 | 434 | 435 | ||
228 | === modified file 'drizzled/optimizer/range.cc' | |||
229 | --- drizzled/optimizer/range.cc 2010-08-06 11:21:12 +0000 | |||
230 | +++ drizzled/optimizer/range.cc 2010-08-26 04:32:43 +0000 | |||
231 | @@ -132,6 +132,7 @@ | |||
232 | 132 | #include "drizzled/records.h" | 132 | #include "drizzled/records.h" |
233 | 133 | #include "drizzled/internal/my_sys.h" | 133 | #include "drizzled/internal/my_sys.h" |
234 | 134 | #include "drizzled/internal/iocache.h" | 134 | #include "drizzled/internal/iocache.h" |
235 | 135 | #include "drizzled/time_profile.h" | ||
236 | 135 | 136 | ||
237 | 136 | #include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */ | 137 | #include "drizzled/temporal.h" /* Needed in get_mm_leaf() for timestamp -> datetime comparisons */ |
238 | 137 | 138 | ||
239 | @@ -420,6 +421,7 @@ | |||
240 | 420 | 421 | ||
241 | 421 | bool optimizer::SqlSelect::skip_record() | 422 | bool optimizer::SqlSelect::skip_record() |
242 | 422 | { | 423 | { |
243 | 424 | BLOCK_MICRO_SEC_TIMER("optimizer::SqlSelect::skip_record"); | ||
244 | 423 | return (cond ? cond->val_int() == 0 : 0); | 425 | return (cond ? cond->val_int() == 0 : 0); |
245 | 424 | } | 426 | } |
246 | 425 | 427 | ||
247 | 426 | 428 | ||
248 | === modified file 'drizzled/session.cc' | |||
249 | --- drizzled/session.cc 2010-08-24 16:45:09 +0000 | |||
250 | +++ drizzled/session.cc 2010-08-26 04:32:43 +0000 | |||
251 | @@ -47,6 +47,7 @@ | |||
252 | 47 | #include "drizzled/pthread_globals.h" | 47 | #include "drizzled/pthread_globals.h" |
253 | 48 | #include "drizzled/transaction_services.h" | 48 | #include "drizzled/transaction_services.h" |
254 | 49 | #include "drizzled/drizzled.h" | 49 | #include "drizzled/drizzled.h" |
255 | 50 | #include "drizzled/time_profile.h" | ||
256 | 50 | 51 | ||
257 | 51 | #include "drizzled/table_share_instance.h" | 52 | #include "drizzled/table_share_instance.h" |
258 | 52 | 53 | ||
259 | @@ -160,6 +161,7 @@ | |||
260 | 160 | scheduler(NULL), | 161 | scheduler(NULL), |
261 | 161 | scheduler_arg(NULL), | 162 | scheduler_arg(NULL), |
262 | 162 | lock_id(&main_lock_id), | 163 | lock_id(&main_lock_id), |
263 | 164 | pThreadProfile(NULL), | ||
264 | 163 | user_time(0), | 165 | user_time(0), |
265 | 164 | ha_data(plugin::num_trx_monitored_objects), | 166 | ha_data(plugin::num_trx_monitored_objects), |
266 | 165 | arg_of_last_insert_id_function(false), | 167 | arg_of_last_insert_id_function(false), |
267 | @@ -254,7 +256,7 @@ | |||
268 | 254 | thr_lock_owner_init(&main_lock_id, &lock_info); | 256 | thr_lock_owner_init(&main_lock_id, &lock_info); |
269 | 255 | 257 | ||
270 | 256 | m_internal_handler= NULL; | 258 | m_internal_handler= NULL; |
272 | 257 | 259 | pThreadProfile = new drizzled::timer::ThreadProfile(); | |
273 | 258 | plugin::EventObserver::registerSessionEvents(*this); | 260 | plugin::EventObserver::registerSessionEvents(*this); |
274 | 259 | } | 261 | } |
275 | 260 | 262 | ||
276 | @@ -391,7 +393,10 @@ | |||
277 | 391 | pthread_setspecific(THR_Session, 0); | 393 | pthread_setspecific(THR_Session, 0); |
278 | 392 | 394 | ||
279 | 393 | plugin::Logging::postEndDo(this); | 395 | plugin::Logging::postEndDo(this); |
281 | 394 | plugin::EventObserver::deregisterSessionEvents(*this); | 396 | plugin::EventObserver::deregisterSessionEvents(*this); |
282 | 397 | |||
283 | 398 | delete pThreadProfile; | ||
284 | 399 | pThreadProfile = NULL; | ||
285 | 395 | 400 | ||
286 | 396 | /* Ensure that no one is using Session */ | 401 | /* Ensure that no one is using Session */ |
287 | 397 | LOCK_delete.unlock(); | 402 | LOCK_delete.unlock(); |
288 | 398 | 403 | ||
289 | === modified file 'drizzled/session.h' | |||
290 | --- drizzled/session.h 2010-08-24 16:45:09 +0000 | |||
291 | +++ drizzled/session.h 2010-08-26 04:32:43 +0000 | |||
292 | @@ -80,6 +80,11 @@ | |||
293 | 80 | struct st_my_thread_var; | 80 | struct st_my_thread_var; |
294 | 81 | } | 81 | } |
295 | 82 | 82 | ||
296 | 83 | namespace timer | ||
297 | 84 | { | ||
298 | 85 | class ThreadProfile; | ||
299 | 86 | } | ||
300 | 87 | |||
301 | 83 | class Lex_input_stream; | 88 | class Lex_input_stream; |
302 | 84 | class user_var_entry; | 89 | class user_var_entry; |
303 | 85 | class CopyField; | 90 | class CopyField; |
304 | @@ -418,7 +423,18 @@ | |||
305 | 418 | struct system_status_var status_var; /**< Session-local status counters */ | 423 | struct system_status_var status_var; /**< Session-local status counters */ |
306 | 419 | THR_LOCK_INFO lock_info; /**< Locking information for this session */ | 424 | THR_LOCK_INFO lock_info; /**< Locking information for this session */ |
307 | 420 | THR_LOCK_OWNER main_lock_id; /**< To use for conventional queries */ | 425 | THR_LOCK_OWNER main_lock_id; /**< To use for conventional queries */ |
309 | 421 | THR_LOCK_OWNER *lock_id; /**< If not main_lock_id, points to the lock_id of a cursor. */ | 426 | THR_LOCK_OWNER *lock_id; /**< If not main_lock_id, points to the lock_id of a |
310 | 427 | *cursor. */ | ||
311 | 428 | |||
312 | 429 | /** | ||
313 | 430 | ThreadProfile class has been created to handle time-profiling related | ||
314 | 431 | information for individual threads.(so as to reduce complexity of mutex etc | ||
315 | 432 | in writing profiling classes) This is currenly hung off session object | ||
316 | 433 | assuming it would be there per connection. Other alternative is to create | ||
317 | 434 | pthread_key_t specifically for profiling and put object of threadProfile | ||
318 | 435 | class there. | ||
319 | 436 | */ | ||
320 | 437 | timer::ThreadProfile* pThreadProfile; /**< Data structure required for time profiling*/ | ||
321 | 422 | private: | 438 | private: |
322 | 423 | boost::mutex LOCK_delete; /**< Locked before session is deleted */ | 439 | boost::mutex LOCK_delete; /**< Locked before session is deleted */ |
323 | 424 | public: | 440 | public: |
324 | @@ -432,7 +448,10 @@ | |||
325 | 432 | { | 448 | { |
326 | 433 | LOCK_delete.unlock(); | 449 | LOCK_delete.unlock(); |
327 | 434 | } | 450 | } |
329 | 435 | 451 | timer::ThreadProfile& getThreadProfile() const { | |
330 | 452 | return *pThreadProfile; | ||
331 | 453 | } | ||
332 | 454 | |||
333 | 436 | /** | 455 | /** |
334 | 437 | * A peek into the query string for the session. This is a best effort | 456 | * A peek into the query string for the session. This is a best effort |
335 | 438 | * delivery, there is no guarantee whether the content is meaningful. | 457 | * delivery, there is no guarantee whether the content is meaningful. |
336 | 439 | 458 | ||
337 | === modified file 'drizzled/sql_parse.cc' | |||
338 | --- drizzled/sql_parse.cc 2010-08-24 16:45:09 +0000 | |||
339 | +++ drizzled/sql_parse.cc 2010-08-26 04:32:43 +0000 | |||
340 | @@ -41,6 +41,7 @@ | |||
341 | 41 | #include "drizzled/probes.h" | 41 | #include "drizzled/probes.h" |
342 | 42 | #include "drizzled/session_list.h" | 42 | #include "drizzled/session_list.h" |
343 | 43 | #include "drizzled/global_charset_info.h" | 43 | #include "drizzled/global_charset_info.h" |
344 | 44 | #include "drizzled/time_profile.h" | ||
345 | 44 | 45 | ||
346 | 45 | #include "drizzled/plugin/logging.h" | 46 | #include "drizzled/plugin/logging.h" |
347 | 46 | #include "drizzled/plugin/query_rewrite.h" | 47 | #include "drizzled/plugin/query_rewrite.h" |
348 | @@ -214,6 +215,7 @@ | |||
349 | 214 | } | 215 | } |
350 | 215 | case COM_QUERY: | 216 | case COM_QUERY: |
351 | 216 | { | 217 | { |
352 | 218 | START_PROFILING_PHASE("query", "microsec"); | ||
353 | 217 | if (! session->readAndStoreQuery(packet, packet_length)) | 219 | if (! session->readAndStoreQuery(packet, packet_length)) |
354 | 218 | break; // fatal error is set | 220 | break; // fatal error is set |
355 | 219 | DRIZZLE_QUERY_START(session->query.c_str(), | 221 | DRIZZLE_QUERY_START(session->query.c_str(), |
356 | @@ -222,7 +224,16 @@ | |||
357 | 222 | 224 | ||
358 | 223 | plugin::QueryRewriter::rewriteQuery(session->db, session->query); | 225 | plugin::QueryRewriter::rewriteQuery(session->db, session->query); |
359 | 224 | mysql_parse(session, session->query.c_str(), session->query.length()); | 226 | mysql_parse(session, session->query.c_str(), session->query.length()); |
361 | 225 | 227 | #if 0 | |
362 | 228 | stringstream ss; | ||
363 | 229 | GET_ALL_PROFILING_RESULT(ss); | ||
364 | 230 | errmsg_printf(ERRMSG_LVL_DBUG, | ||
365 | 231 | "--------------------Profile Output------------------\n"); | ||
366 | 232 | errmsg_printf(ERRMSG_LVL_DBUG,"Command : %s\n", session->query.c_str()); | ||
367 | 233 | errmsg_printf(ERRMSG_LVL_DBUG,ss.str().c_str()); | ||
368 | 234 | errmsg_printf(ERRMSG_LVL_DBUG, | ||
369 | 235 | "---------------------------x------------------------\n"); | ||
370 | 236 | #endif | ||
371 | 226 | break; | 237 | break; |
372 | 227 | } | 238 | } |
373 | 228 | case COM_QUIT: | 239 | case COM_QUIT: |
374 | @@ -716,6 +727,7 @@ | |||
375 | 716 | 727 | ||
376 | 717 | void mysql_parse(Session *session, const char *inBuf, uint32_t length) | 728 | void mysql_parse(Session *session, const char *inBuf, uint32_t length) |
377 | 718 | { | 729 | { |
378 | 730 | drizzled::timer::FastTimerMicroSecPrec autoObj("mysql_parse"); | ||
379 | 719 | uint64_t start_time= my_getsystime(); | 731 | uint64_t start_time= my_getsystime(); |
380 | 720 | lex_start(session); | 732 | lex_start(session); |
381 | 721 | session->reset_for_next_command(); | 733 | session->reset_for_next_command(); |
382 | 722 | 734 | ||
383 | === modified file 'drizzled/sql_select.cc' | |||
384 | --- drizzled/sql_select.cc 2010-08-21 04:05:07 +0000 | |||
385 | +++ drizzled/sql_select.cc 2010-08-26 04:32:43 +0000 | |||
386 | @@ -6594,8 +6594,6 @@ | |||
387 | 6594 | /* QQ: session may not be set for sub queries, but this should be fixed */ | 6594 | /* QQ: session may not be set for sub queries, but this should be fixed */ |
388 | 6595 | if(not session) | 6595 | if(not session) |
389 | 6596 | session= current_session; | 6596 | session= current_session; |
390 | 6597 | |||
391 | 6598 | |||
392 | 6599 | str->append(STRING_WITH_LEN("select ")); | 6597 | str->append(STRING_WITH_LEN("select ")); |
393 | 6600 | 6598 | ||
394 | 6601 | /* First add options */ | 6599 | /* First add options */ |
395 | 6602 | 6600 | ||
396 | === added file 'drizzled/time_profile.h' | |||
397 | --- drizzled/time_profile.h 1970-01-01 00:00:00 +0000 | |||
398 | +++ drizzled/time_profile.h 2010-08-26 04:32:43 +0000 | |||
399 | @@ -0,0 +1,614 @@ | |||
400 | 1 | /* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*- | ||
401 | 2 | * vim:expandtab:shiftwidth=2:tabstop=2:smarttab: | ||
402 | 3 | * | ||
403 | 4 | * Copyright (C) 2010 Prafulla Tekawade | ||
404 | 5 | * | ||
405 | 6 | * This program is free software; you can redistribute it and/or modify | ||
406 | 7 | * it under the terms of the GNU General Public License as published by | ||
407 | 8 | * the Free Software Foundation; version 2 of the License. | ||
408 | 9 | * | ||
409 | 10 | * This program is distributed in the hope that it will be useful, | ||
410 | 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
411 | 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
412 | 13 | * GNU General Public License for more details. | ||
413 | 14 | * | ||
414 | 15 | * You should have received a copy of the GNU General Public License | ||
415 | 16 | * along with this program; if not, write to the Free Software | ||
416 | 17 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
417 | 18 | */ | ||
418 | 19 | |||
419 | 20 | #ifndef DRIZZLED_TIME_PROFILE_H | ||
420 | 21 | #define DRIZZLED_TIME_PROFILE_H | ||
421 | 22 | |||
422 | 23 | #include "drizzled/drizzle_time.h" | ||
423 | 24 | #if TIME_WITH_SYS_TIME | ||
424 | 25 | #include <sys/time.h> | ||
425 | 26 | #include <time.h> | ||
426 | 27 | #else | ||
427 | 28 | #if HAVE_SYS_TIME_H | ||
428 | 29 | #include <sys/time.h> | ||
429 | 30 | #else | ||
430 | 31 | #include <time.h> | ||
431 | 32 | #endif | ||
432 | 33 | |||
433 | 34 | #endif | ||
434 | 35 | |||
435 | 36 | #include <iostream> | ||
436 | 37 | #include <stdint.h> | ||
437 | 38 | #include <math.h> | ||
438 | 39 | #include <stdio.h> | ||
439 | 40 | #include <cassert> | ||
440 | 41 | #include <map> | ||
441 | 42 | #include <stack> | ||
442 | 43 | #include <sstream> | ||
443 | 44 | #include <iostream> | ||
444 | 45 | #include "drizzled/session.h" | ||
445 | 46 | #include "drizzled/errmsg_print.h" | ||
446 | 47 | |||
447 | 48 | #define ONE_BILLION 1000000000ULL | ||
448 | 49 | #define ONE_MILLION 1000000 | ||
449 | 50 | #define ONE_THOUSAND 1000 | ||
450 | 51 | |||
451 | 52 | |||
452 | 53 | #if 0 | ||
453 | 54 | #define ENABLE_RTDC_BASED_TIMER | ||
454 | 55 | #endif | ||
455 | 56 | |||
456 | 57 | |||
457 | 58 | //Set this to 1, if you want to profile the code. | ||
458 | 59 | #if 1 | ||
459 | 60 | #define TIME_PROFILE_ON 1 | ||
460 | 61 | #endif | ||
461 | 62 | |||
462 | 63 | #define _CONCAT(a,b) a ## b | ||
463 | 64 | #define CONCAT(a,b) _CONCAT(a, b) | ||
464 | 65 | |||
465 | 66 | namespace drizzled { | ||
466 | 67 | namespace timer { | ||
467 | 68 | |||
468 | 69 | inline uint64_t getSecTime(); | ||
469 | 70 | inline uint64_t getMicroSecTime(); | ||
470 | 71 | inline uint64_t getNanoSecTime(); | ||
471 | 72 | inline uint64_t getMilliSecTime(); | ||
472 | 73 | |||
473 | 74 | inline ThreadProfile& thp(); | ||
474 | 75 | inline void th_pushProfilePhase(const char* sPhaseName, | ||
475 | 76 | const char* sScale); | ||
476 | 77 | inline void th_popProfilePhase(); | ||
477 | 78 | inline bool useRtdcImpl(); | ||
478 | 79 | inline bool useClockGetTimeImpl(); | ||
479 | 80 | inline const char* getTimePrecToStr(int ePrecRange); | ||
480 | 81 | |||
481 | 82 | |||
482 | 83 | enum | ||
483 | 84 | { | ||
484 | 85 | eRtdcImpl = 0, | ||
485 | 86 | eClockTimeImpl, | ||
486 | 87 | eGetToDImpl | ||
487 | 88 | }; | ||
488 | 89 | |||
489 | 90 | enum | ||
490 | 91 | { | ||
491 | 92 | eSecPrec = 0, | ||
492 | 93 | eMilliSecPrec, | ||
493 | 94 | eMicroSecPrec, | ||
494 | 95 | eNanoSecPrec | ||
495 | 96 | }; | ||
496 | 97 | |||
497 | 98 | #ifdef TIME_PROFILE_ON | ||
498 | 99 | |||
499 | 100 | #define BLOCK_NANO_SEC_TIMER(sBlockName) drizzled::timer::FastTimerNanoSecPrec CONCAT(autoObj, __LINE__ )(sBlockName); | ||
500 | 101 | #define BLOCK_MICRO_SEC_TIMER(sBlockName) drizzled::timer::FastTimerMicroSecPrec CONCAT(autoObj, __LINE__ )(sBlockName); | ||
501 | 102 | #define BLOCK_MILLI_SEC_TIMER(sBlockName) drizzled::timer::FastTimerMilliSecPrec CONCAT(autoObj, __LINE__ )(sBlockName); | ||
502 | 103 | #define BLOCK_SEC_TIMER(sBlockName) drizzled::timer::FastTimerSecPrec CONCAT(autoObj, __LINE__ )(sBlockName); | ||
503 | 104 | |||
504 | 105 | #define START_PROFILING_PHASE(name, scale) \ | ||
505 | 106 | drizzled::timer::th_pushProfilePhase(name, scale); \ | ||
506 | 107 | drizzled::timer::AutoProfPhase autoPhase; | ||
507 | 108 | |||
508 | 109 | |||
509 | 110 | #define GET_ALL_PROFILING_RESULT(outputStream) drizzled::timer::thp().printAllOpTime(outputStream); | ||
510 | 111 | |||
511 | 112 | #else | ||
512 | 113 | |||
513 | 114 | #define START_PROFILING_PHASE(name, scale) | ||
514 | 115 | #define END_PROFILING_AND_COLLECT_RESULT(outputStream) | ||
515 | 116 | #define BLOCK_NANO_SEC_TIMER(sBlockName) | ||
516 | 117 | #define BLOCK_MICRO_SEC_TIMER(sBlockName) | ||
517 | 118 | #define BLOCK_MILLI_SEC_TIMER(sBlockName) | ||
518 | 119 | #define BLOCK_SEC_TIMER(sBlockName) | ||
519 | 120 | #define GET_ALL_PROFILING_RESULT(outputStream) | ||
520 | 121 | |||
521 | 122 | |||
522 | 123 | #endif | ||
523 | 124 | |||
524 | 125 | class TimeProfile | ||
525 | 126 | { | ||
526 | 127 | private: | ||
527 | 128 | typedef std::pair<uint64_t, uint64_t> AccOccTimePair; | ||
528 | 129 | typedef std::map<std::string, AccOccTimePair> OpTimeMap; | ||
529 | 130 | public: | ||
530 | 131 | |||
531 | 132 | TimeProfile():prof_name("{NoProfileName}"), | ||
532 | 133 | scale("NoScale") | ||
533 | 134 | { } | ||
534 | 135 | TimeProfile(const char* _prof_name, | ||
535 | 136 | const char* _scale) : prof_name(_prof_name), | ||
536 | 137 | scale(_scale) | ||
537 | 138 | { } | ||
538 | 139 | |||
539 | 140 | void addOpTime(const char* name, uint64_t time) | ||
540 | 141 | { | ||
541 | 142 | std::pair<OpTimeMap::iterator, bool> ins_res_pair = | ||
542 | 143 | opTimeMap.insert(std::make_pair(name, std::make_pair(time,1))); | ||
543 | 144 | |||
544 | 145 | if( !ins_res_pair.second ) { //If opName already exists, accumulate numTime | ||
545 | 146 | //and increament occ counter. | ||
546 | 147 | (ins_res_pair.first)->second.first += time; | ||
547 | 148 | (ins_res_pair.first)->second.second++; | ||
548 | 149 | } | ||
549 | 150 | } | ||
550 | 151 | |||
551 | 152 | void printOpTime(std::ostream& oss) | ||
552 | 153 | { | ||
553 | 154 | OpTimeMap::iterator itr = opTimeMap.begin(); | ||
554 | 155 | oss << prof_name << std::endl; | ||
555 | 156 | oss << "{" << std::endl; | ||
556 | 157 | while( itr != opTimeMap.end() ) | ||
557 | 158 | { | ||
558 | 159 | oss << itr->first; | ||
559 | 160 | oss << ", acc= " << itr->second.first << " " << scale; | ||
560 | 161 | oss << ", occ=" << itr->second.second << std::endl; | ||
561 | 162 | itr++; | ||
562 | 163 | } | ||
563 | 164 | oss << "}" << std::endl; | ||
564 | 165 | } | ||
565 | 166 | |||
566 | 167 | private: | ||
567 | 168 | OpTimeMap opTimeMap; | ||
568 | 169 | const char* prof_name; | ||
569 | 170 | const char* scale; | ||
570 | 171 | }; | ||
571 | 172 | |||
572 | 173 | |||
573 | 174 | class ThreadProfile | ||
574 | 175 | { | ||
575 | 176 | public: | ||
576 | 177 | |||
577 | 178 | ThreadProfile():time_profile_stack(), | ||
578 | 179 | profile_data() { } | ||
579 | 180 | ~ThreadProfile() { } | ||
580 | 181 | |||
581 | 182 | TimeProfile* cur() | ||
582 | 183 | { | ||
583 | 184 | if( time_profile_stack.empty() ) | ||
584 | 185 | return NULL; | ||
585 | 186 | return &(time_profile_stack.top()); | ||
586 | 187 | } | ||
587 | 188 | void pushProfilePhase(const char* sPhaseName, const char* sScale) | ||
588 | 189 | { | ||
589 | 190 | time_profile_stack.push(TimeProfile(sPhaseName, sScale)); | ||
590 | 191 | } | ||
591 | 192 | |||
592 | 193 | void popProfilePhase() | ||
593 | 194 | { | ||
594 | 195 | if( time_profile_stack.empty() ) | ||
595 | 196 | return; | ||
596 | 197 | time_profile_stack.pop(); | ||
597 | 198 | } | ||
598 | 199 | |||
599 | 200 | void printAllOpTime(std::ostream& oss) | ||
600 | 201 | { | ||
601 | 202 | while( !time_profile_stack.empty() ) | ||
602 | 203 | { | ||
603 | 204 | time_profile_stack.top().printOpTime(oss); | ||
604 | 205 | oss << std::endl; | ||
605 | 206 | time_profile_stack.pop(); | ||
606 | 207 | } | ||
607 | 208 | std::vector<std::string>::const_iterator it = profile_data.begin(); | ||
608 | 209 | while(it != profile_data.end()) | ||
609 | 210 | { | ||
610 | 211 | oss << *it; | ||
611 | 212 | oss << std::endl; | ||
612 | 213 | it++; | ||
613 | 214 | } | ||
614 | 215 | profile_data.clear(); | ||
615 | 216 | } | ||
616 | 217 | |||
617 | 218 | void saveProfileData(const char* pData) | ||
618 | 219 | { | ||
619 | 220 | std::string sStr(pData); | ||
620 | 221 | if( sStr.length() ) | ||
621 | 222 | profile_data.push_back(sStr); | ||
622 | 223 | } | ||
623 | 224 | private: | ||
624 | 225 | std::stack<TimeProfile> time_profile_stack; | ||
625 | 226 | std::vector<std::string> profile_data; | ||
626 | 227 | }; | ||
627 | 228 | |||
628 | 229 | |||
629 | 230 | inline ThreadProfile& thp() | ||
630 | 231 | { | ||
631 | 232 | return current_session->getThreadProfile(); | ||
632 | 233 | } | ||
633 | 234 | |||
634 | 235 | inline TimeProfile* th_getProf() | ||
635 | 236 | { | ||
636 | 237 | return thp().cur(); | ||
637 | 238 | } | ||
638 | 239 | |||
639 | 240 | inline void th_pushProfilePhase(const char* sPhaseName, | ||
640 | 241 | const char* sScale) | ||
641 | 242 | { | ||
642 | 243 | thp().pushProfilePhase(sPhaseName, sScale); | ||
643 | 244 | } | ||
644 | 245 | |||
645 | 246 | inline void th_popProfilePhase() | ||
646 | 247 | { | ||
647 | 248 | thp().popProfilePhase(); | ||
648 | 249 | } | ||
649 | 250 | |||
650 | 251 | |||
651 | 252 | class AutoProfPhase | ||
652 | 253 | { | ||
653 | 254 | public: | ||
654 | 255 | explicit AutoProfPhase() | ||
655 | 256 | { } | ||
656 | 257 | void popAndSaveProfileData() const | ||
657 | 258 | { | ||
658 | 259 | std::stringstream ss; | ||
659 | 260 | if( th_getProf() ) | ||
660 | 261 | th_getProf()->printOpTime(ss); | ||
661 | 262 | th_popProfilePhase(); | ||
662 | 263 | thp().saveProfileData(ss.str().c_str()); | ||
663 | 264 | } | ||
664 | 265 | |||
665 | 266 | ~AutoProfPhase() { | ||
666 | 267 | popAndSaveProfileData(); | ||
667 | 268 | } | ||
668 | 269 | }; | ||
669 | 270 | |||
670 | 271 | |||
671 | 272 | namespace rtdcimpl { | ||
672 | 273 | |||
673 | 274 | inline uint64_t getTimeInNanoSec(); | ||
674 | 275 | inline uint64_t getTimeInMicroSec(); | ||
675 | 276 | inline uint64_t getTimeInMilliSec(); | ||
676 | 277 | inline uint64_t getTimeInSec(); | ||
677 | 278 | inline uint64_t getProcTimestampCounter(); | ||
678 | 279 | inline double getProcTimerstampScale(); | ||
679 | 280 | |||
680 | 281 | inline uint64_t getProcTimestampCounter() | ||
681 | 282 | { | ||
682 | 283 | uint64_t cur_time_cntr; | ||
683 | 284 | #if defined(__GNUC__) && defined(__i386__) | ||
684 | 285 | asm volatile("rdtsc":"=A"(cur_time_cntr)); | ||
685 | 286 | #elif defined(__GNUC__) && defined(__x86_64__) | ||
686 | 287 | uint64_t hi, lo; | ||
687 | 288 | asm volatile("rdtc":"=a"(hi), "=d"(lo)); | ||
688 | 289 | cur_time_cntr = (((uint64_t)hi << 32) || lo); | ||
689 | 290 | #else | ||
690 | 291 | cur_time_cntr = 0; | ||
691 | 292 | assert(!"Aborted: rdtsc unimplemented for this configuration."); | ||
692 | 293 | #endif | ||
693 | 294 | return cur_time_cntr;; | ||
694 | 295 | } | ||
695 | 296 | |||
696 | 297 | //Calculating how many seconds are spent in a tick | ||
697 | 298 | //so that we can use this information to get nano/milli/micro secs | ||
698 | 299 | inline double getProcTimerstampScale() | ||
699 | 300 | { | ||
700 | 301 | int seconds_to_test = 2; | ||
701 | 302 | uint64_t delta_time = 0, retry_num = 3; | ||
702 | 303 | do | ||
703 | 304 | { | ||
704 | 305 | uint64_t beforeTime = getProcTimestampCounter(); | ||
705 | 306 | sleep(seconds_to_test); | ||
706 | 307 | delta_time = getProcTimestampCounter() - beforeTime; | ||
707 | 308 | } while(retry_num-- && delta_time > 0); | ||
708 | 309 | if (delta_time <= 0 ) | ||
709 | 310 | return 0; | ||
710 | 311 | double scale = (double)seconds_to_test/delta_time; | ||
711 | 312 | return scale; | ||
712 | 313 | } | ||
713 | 314 | #ifdef ENABLE_RTDC_BASED_TIMER | ||
714 | 315 | static double processort_counter_scale = getProcTimerstampScale(); | ||
715 | 316 | #else | ||
716 | 317 | static double processort_counter_scale = 0; | ||
717 | 318 | #endif | ||
718 | 319 | inline uint64_t getTimeInSec() | ||
719 | 320 | { | ||
720 | 321 | uint64_t proc_counter_value = getProcTimestampCounter(); | ||
721 | 322 | return proc_counter_value * processort_counter_scale; | ||
722 | 323 | } | ||
723 | 324 | |||
724 | 325 | inline uint64_t getTimeInMilliSec() | ||
725 | 326 | { | ||
726 | 327 | uint64_t proc_counter_value = getProcTimestampCounter(); | ||
727 | 328 | return proc_counter_value * ONE_THOUSAND * processort_counter_scale; | ||
728 | 329 | } | ||
729 | 330 | |||
730 | 331 | inline uint64_t getTimeInMicroSec() | ||
731 | 332 | { | ||
732 | 333 | uint64_t proc_counter_value = getProcTimestampCounter(); | ||
733 | 334 | return proc_counter_value * ONE_MILLION * processort_counter_scale; | ||
734 | 335 | } | ||
735 | 336 | |||
736 | 337 | inline uint64_t getTimeInNanoSec() | ||
737 | 338 | { | ||
738 | 339 | uint64_t proc_counter_value = getProcTimestampCounter(); | ||
739 | 340 | return proc_counter_value * ONE_BILLION * processort_counter_scale; | ||
740 | 341 | } | ||
741 | 342 | } | ||
742 | 343 | |||
743 | 344 | namespace todimpl { | ||
744 | 345 | inline uint64_t getTimeInNanoSec(); | ||
745 | 346 | inline uint64_t getTimeInMicroSec(); | ||
746 | 347 | inline uint64_t getTimeInMilliSec(); | ||
747 | 348 | inline uint64_t getTimeInSec(); | ||
748 | 349 | |||
749 | 350 | inline uint64_t getTimeInMilliSec() | ||
750 | 351 | { | ||
751 | 352 | struct timeval cur_time; | ||
752 | 353 | gettimeofday(&cur_time, NULL); | ||
753 | 354 | return cur_time.tv_sec*ONE_THOUSAND + cur_time.tv_usec/ONE_THOUSAND; | ||
754 | 355 | } | ||
755 | 356 | |||
756 | 357 | inline uint64_t getTimeInMicroSec() | ||
757 | 358 | { | ||
758 | 359 | struct timeval cur_time; | ||
759 | 360 | gettimeofday(&cur_time, NULL); | ||
760 | 361 | return cur_time.tv_sec*ONE_MILLION + cur_time.tv_usec; | ||
761 | 362 | } | ||
762 | 363 | |||
763 | 364 | inline uint64_t getTimeInNanoSec() | ||
764 | 365 | { | ||
765 | 366 | struct timeval cur_time; | ||
766 | 367 | gettimeofday(&cur_time, NULL); | ||
767 | 368 | return cur_time.tv_sec*ONE_BILLION + cur_time.tv_usec*ONE_THOUSAND; | ||
768 | 369 | } | ||
769 | 370 | |||
770 | 371 | inline uint64_t getTimeInSec() | ||
771 | 372 | { | ||
772 | 373 | struct timeval cur_time; | ||
773 | 374 | gettimeofday(&cur_time, NULL); | ||
774 | 375 | return cur_time.tv_sec*ONE_BILLION + cur_time.tv_usec*ONE_MILLION; | ||
775 | 376 | } | ||
776 | 377 | } | ||
777 | 378 | |||
778 | 379 | namespace clockimpl { | ||
779 | 380 | inline uint64_t getTimeInNanoSec(); | ||
780 | 381 | inline uint64_t getTimeInMicroSec(); | ||
781 | 382 | inline uint64_t getTimeInMilliSec(); | ||
782 | 383 | inline uint64_t getTimeInSec(); | ||
783 | 384 | inline void getClockTime(struct timespec& tp); | ||
784 | 385 | |||
785 | 386 | inline uint64_t getTimeInNanoSec() | ||
786 | 387 | { | ||
787 | 388 | struct timespec tp; | ||
788 | 389 | clock_gettime(CLOCK_REALTIME, &tp); | ||
789 | 390 | return tp.tv_sec*ONE_BILLION + tp.tv_nsec; | ||
790 | 391 | } | ||
791 | 392 | |||
792 | 393 | inline uint64_t getTimeInMicroSec() | ||
793 | 394 | { | ||
794 | 395 | struct timespec tp; | ||
795 | 396 | clock_gettime(CLOCK_REALTIME, &tp); | ||
796 | 397 | return (uint64_t)tp.tv_sec*ONE_MILLION + (uint64_t)tp.tv_nsec/ONE_THOUSAND; | ||
797 | 398 | } | ||
798 | 399 | |||
799 | 400 | inline uint64_t getTimeInMilliSec() | ||
800 | 401 | { | ||
801 | 402 | struct timespec tp; | ||
802 | 403 | clock_gettime(CLOCK_REALTIME, &tp); | ||
803 | 404 | return (uint64_t)tp.tv_sec*ONE_THOUSAND + (uint64_t)tp.tv_nsec/ONE_MILLION; | ||
804 | 405 | } | ||
805 | 406 | |||
806 | 407 | inline uint64_t getTimeInSec() | ||
807 | 408 | { | ||
808 | 409 | struct timespec tp; | ||
809 | 410 | return (uint64_t)tp.tv_sec + (uint64_t)tp.tv_nsec/ONE_BILLION; | ||
810 | 411 | } | ||
811 | 412 | |||
812 | 413 | inline void getClockTime(struct timespec& tp) | ||
813 | 414 | { | ||
814 | 415 | #if defined(HAVE_CLOCK_GETTIME) | ||
815 | 416 | clock_gettime(CLOCK_REALTIME, &tp); | ||
816 | 417 | #else | ||
817 | 418 | tp.tv_sec = 0; | ||
818 | 419 | tp.tv_nsec = 0; | ||
819 | 420 | errmsg_printf(ERRMSG_LVL_ERROR, | ||
820 | 421 | "clock_gettime is not supported on this platform."\ | ||
821 | 422 | "Please use different timer implementation"); | ||
822 | 423 | #endif | ||
823 | 424 | } | ||
824 | 425 | } | ||
825 | 426 | |||
826 | 427 | #if defined(__GNUC__) && defined(__i386__) | ||
827 | 428 | #define HAVE_RTDC_IMPL | ||
828 | 429 | #elif defined(__GNUC__) && defined(__x86_64__) | ||
829 | 430 | #define HAVE_RTDC_IMPL | ||
830 | 431 | #endif | ||
831 | 432 | |||
832 | 433 | inline bool useRtdcImpl() | ||
833 | 434 | { | ||
834 | 435 | #ifdef HAVE_RTDC_IMPL | ||
835 | 436 | return true; | ||
836 | 437 | #else | ||
837 | 438 | return false; | ||
838 | 439 | #endif | ||
839 | 440 | } | ||
840 | 441 | |||
841 | 442 | inline bool useClockGetTimeImpl() | ||
842 | 443 | { | ||
843 | 444 | #ifdef HAVE_CLOCK_GETTIME | ||
844 | 445 | return true; | ||
845 | 446 | #else | ||
846 | 447 | return false; | ||
847 | 448 | #endif | ||
848 | 449 | } | ||
849 | 450 | |||
850 | 451 | |||
851 | 452 | #define GET_TIME(timerimpl, cur_time) { \ | ||
852 | 453 | switch( ePrecRange ) { \ | ||
853 | 454 | case eSecPrec: \ | ||
854 | 455 | cur_time = timerimpl::getTimeInSec(); \ | ||
855 | 456 | break; \ | ||
856 | 457 | case eMilliSecPrec: \ | ||
857 | 458 | cur_time = timerimpl::getTimeInMilliSec(); \ | ||
858 | 459 | break; \ | ||
859 | 460 | case eMicroSecPrec: \ | ||
860 | 461 | cur_time = timerimpl::getTimeInMicroSec(); \ | ||
861 | 462 | break; \ | ||
862 | 463 | case eNanoSecPrec: \ | ||
863 | 464 | cur_time = timerimpl::getTimeInNanoSec(); \ | ||
864 | 465 | break; \ | ||
865 | 466 | } \ | ||
866 | 467 | } \ | ||
867 | 468 | |||
868 | 469 | |||
869 | 470 | |||
870 | 471 | inline const char* getTimePrecToStr(int ePrecRange) | ||
871 | 472 | { | ||
872 | 473 | switch(ePrecRange) { | ||
873 | 474 | case eMilliSecPrec: | ||
874 | 475 | return "milli sec"; | ||
875 | 476 | case eMicroSecPrec: | ||
876 | 477 | return "micro sec"; | ||
877 | 478 | case eNanoSecPrec: | ||
878 | 479 | return "nano sec"; | ||
879 | 480 | case eSecPrec: | ||
880 | 481 | return "sec"; | ||
881 | 482 | |||
882 | 483 | } | ||
883 | 484 | return NULL; | ||
884 | 485 | } | ||
885 | 486 | /** | ||
886 | 487 | * Class to capture timing information for C/C++ block | ||
887 | 488 | * If opName is supplied, it adds this information to currect active Timing | ||
888 | 489 | * profile object. | ||
889 | 490 | * Following are some overhead information for this classes | ||
890 | 491 | * eImplKind = eRtdcImpl (~50 ns on 2.7 GHz intel machine), This went to | ||
891 | 492 | * average ~20 ns for large number of operations (1 million in my example) | ||
892 | 493 | * eImplKind = eClockTimeImpl (~1000 ns on 2.7 GHz intel machine) | ||
893 | 494 | * eImplKind = eGetToDImpl (~1500/2000 ns on 2.7 GHz intel machine) | ||
894 | 495 | */ | ||
895 | 496 | template<int eImplKind , int ePrecRange > | ||
896 | 497 | class AutoOpTimer { | ||
897 | 498 | public: | ||
898 | 499 | explicit AutoOpTimer(const char* sOpName):opr_name(sOpName), begin_time(0) | ||
899 | 500 | { | ||
900 | 501 | acquire(); | ||
901 | 502 | } | ||
902 | 503 | |||
903 | 504 | void acquire() | ||
904 | 505 | { | ||
905 | 506 | switch( eImplKind ) | ||
906 | 507 | { | ||
907 | 508 | case eGetToDImpl: | ||
908 | 509 | GET_TIME(todimpl, begin_time); | ||
909 | 510 | break; | ||
910 | 511 | case eClockTimeImpl: | ||
911 | 512 | GET_TIME(clockimpl, begin_time); | ||
912 | 513 | break; | ||
913 | 514 | case eRtdcImpl: | ||
914 | 515 | GET_TIME(rtdcimpl, begin_time); | ||
915 | 516 | break; | ||
916 | 517 | } | ||
917 | 518 | } | ||
918 | 519 | |||
919 | 520 | uint64_t getBgnTime() const | ||
920 | 521 | { | ||
921 | 522 | return begin_time; | ||
922 | 523 | } | ||
923 | 524 | |||
924 | 525 | static uint64_t getCurTime() | ||
925 | 526 | { | ||
926 | 527 | uint64_t cur_time = 0; | ||
927 | 528 | switch( eImplKind ) | ||
928 | 529 | { | ||
929 | 530 | case eGetToDImpl: | ||
930 | 531 | GET_TIME(todimpl, cur_time); | ||
931 | 532 | break; | ||
932 | 533 | case eClockTimeImpl: | ||
933 | 534 | GET_TIME(clockimpl, cur_time); | ||
934 | 535 | break; | ||
935 | 536 | case eRtdcImpl: | ||
936 | 537 | GET_TIME(rtdcimpl, cur_time); | ||
937 | 538 | break; | ||
938 | 539 | } | ||
939 | 540 | return cur_time; | ||
940 | 541 | } | ||
941 | 542 | |||
942 | 543 | uint64_t getTimeElapsed() const | ||
943 | 544 | { | ||
944 | 545 | uint64_t cur_time = getCurTime(); | ||
945 | 546 | uint64_t diff = (cur_time - begin_time) * (cur_time > begin_time); | ||
946 | 547 | return diff; | ||
947 | 548 | } | ||
948 | 549 | |||
949 | 550 | ~AutoOpTimer() | ||
950 | 551 | { | ||
951 | 552 | uint64_t uTimeElapsed = getTimeElapsed(); | ||
952 | 553 | if( opr_name ) { | ||
953 | 554 | if( th_getProf() ) | ||
954 | 555 | th_getProf()->addOpTime(opr_name, uTimeElapsed); | ||
955 | 556 | } | ||
956 | 557 | } | ||
957 | 558 | private: | ||
958 | 559 | const char* opr_name; | ||
959 | 560 | uint64_t begin_time; | ||
960 | 561 | }; | ||
961 | 562 | |||
962 | 563 | //Rtdc based timer do not give reliable timing information. | ||
963 | 564 | //so by default they are off. One can use them directly if they want in | ||
964 | 565 | //CPU-bound operation by using following Rtdc Timers and setting | ||
965 | 566 | //ENABLE_RTDC_BASED_TIMER macro above. | ||
966 | 567 | typedef AutoOpTimer<eRtdcImpl, eNanoSecPrec> RtdcTimerNanoSecPrec; | ||
967 | 568 | typedef AutoOpTimer<eRtdcImpl, eMilliSecPrec> RtdcTimerMilliSecPrec; | ||
968 | 569 | typedef AutoOpTimer<eRtdcImpl, eMicroSecPrec> RtdcTimerMicroSecPrec; | ||
969 | 570 | typedef AutoOpTimer<eRtdcImpl, eSecPrec> RtdcTimerSecPrec; | ||
970 | 571 | |||
971 | 572 | |||
972 | 573 | #if defined(HAVE_RTDC_IMPL) && defined(ENABLE_RTDC_BASED_TIMER) | ||
973 | 574 | typedef AutoOpTimer<eRtdcImpl, eNanoSecPrec> FastTimerNanoSecPrec; | ||
974 | 575 | typedef AutoOpTimer<eRtdcImpl, eMilliSecPrec> FastTimerMilliSecPrec; | ||
975 | 576 | typedef AutoOpTimer<eRtdcImpl, eMicroSecPrec> FastTimerMicroSecPrec; | ||
976 | 577 | typedef AutoOpTimer<eRtdcImpl, eSecPrec> FastTimerSecPrec; | ||
977 | 578 | #elif defined(HAVE_CLOCK_GETTIME) | ||
978 | 579 | typedef AutoOpTimer<eClockTimeImpl, eNanoSecPrec> FastTimerNanoSecPrec; | ||
979 | 580 | typedef AutoOpTimer<eClockTimeImpl, eMilliSecPrec> FastTimerMilliSecPrec; | ||
980 | 581 | typedef AutoOpTimer<eClockTimeImpl, eMicroSecPrec> FastTimerMicroSecPrec; | ||
981 | 582 | typedef AutoOpTimer<eClockTimeImpl, eSecPrec> FastTimerSecPrec; | ||
982 | 583 | #else | ||
983 | 584 | typedef AutoOpTimer<eGetToDImpl, eNanoSecPrec> FastTimerNanoSecPrec; | ||
984 | 585 | typedef AutoOpTimer<eGetToDImpl, eMilliSecPrec> FastTimerMilliSecPrec; | ||
985 | 586 | typedef AutoOpTimer<eGetToDImpl, eMicroSecPrec> FastTimerMicroSecPrec; | ||
986 | 587 | typedef AutoOpTimer<eGetToDImpl, eSecPrec> FastTimerSecPrec; | ||
987 | 588 | #endif | ||
988 | 589 | |||
989 | 590 | |||
990 | 591 | uint64_t getSecTime() | ||
991 | 592 | { | ||
992 | 593 | return FastTimerSecPrec::getCurTime(); | ||
993 | 594 | } | ||
994 | 595 | |||
995 | 596 | uint64_t getMilliSecTime() | ||
996 | 597 | { | ||
997 | 598 | return FastTimerMilliSecPrec::getCurTime(); | ||
998 | 599 | } | ||
999 | 600 | |||
1000 | 601 | uint64_t getMicroSecTime() | ||
1001 | 602 | { | ||
1002 | 603 | return FastTimerMicroSecPrec::getCurTime(); | ||
1003 | 604 | } | ||
1004 | 605 | |||
1005 | 606 | uint64_t getNanoSecTime() | ||
1006 | 607 | { | ||
1007 | 608 | return FastTimerNanoSecPrec::getCurTime(); | ||
1008 | 609 | } | ||
1009 | 610 | }/* namespace timer */ | ||
1010 | 611 | }/*namespace drizzled*/ | ||
1011 | 612 | |||
1012 | 613 | |||
1013 | 614 | #endif |
Hi
This branch has code from my other branches too.
Could you please look at the following files ? filesort. cc drizzled/session.cc sql_parse. cc drizzled/ time_profile. h optimizer/ range.cc
drizzled/
drizzled/session.h
drizzled/
drizzled/
Once it is reviewed, I will create separate branch with only
profiling related code. or hopefully by then my other changes
should already be in trunk.