2 * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 #include <sys/time.h> // gettimeofday
24 #include "statistics.h"
31 #include <sys/utsname.h>
32 #include <sys/resource.h>
37 #include "statistics.h"
39 #define MAX_UINT32 (0xFFFFFFFFL)
40 #define MAX_UINT64 (0xFFFFFFFFFFFFFFFFLL)
43 #define MM_TA_MAX_ACCUM 100
46 typedef struct _mm_ta_accum_item
48 unsigned long long elapsed_accum;
49 unsigned long num_calls;
50 unsigned long long elapsed_min;
51 unsigned long long elapsed_max;
52 unsigned long long first_start;
53 unsigned long long last_end;
57 unsigned long long timestamp;
63 static void PrintLog(const char *file, int line, const char *msg, ...)
68 fprintf(stderr ,"[STAT] %s:%d:",file, line);
69 vfprintf(stderr ,msg, va);
70 fprintf(stderr, "\n");
74 #define MyPrintf(...) PrintLog(__FILE__, __LINE__, ##__VA_ARGS__ )
78 static void __free_accums(void);
79 static int __get_accum_index(const char* name);
83 static mm_ta_accum_item ** g_accums = NULL;
84 static int g_accum_index = 0;
85 static int g_accum_longest_name = 0;
86 static unsigned long long g_accum_first_time = MAX_UINT64; // jmlee
96 g_accums = (mm_ta_accum_item **) calloc (1, MM_TA_MAX_ACCUM * sizeof(mm_ta_accum_item *) );
103 g_accum_first_time = MAX_UINT64;
108 int PERF_DEINIT(void)
117 g_accum_first_time = MAX_UINT64;
123 static int __get_accum_index(const char* name)
130 for ( i = 0; i < g_accum_index; i++ )
132 if ( strcmp( name, g_accums[i]->name ) == 0 )
139 static void __free_accums(void)
146 for ( i = 0; i < g_accum_index; i++ )
150 if ( g_accums[i]->name )
151 free ( g_accums[i]->name );
153 free ( g_accums[i] );
160 g_accum_longest_name = 0;
168 int mm_ta_accum_item_begin(const char* name, bool show, const char* filename, int line)
170 mm_ta_accum_item * accum = NULL;
178 if ( g_accum_index == MM_TA_MAX_ACCUM )
184 name_len = strlen(name);
188 // if 'name' is new one. create new item.
189 if ( (index = __get_accum_index(name)) == -1 )
191 accum = ( mm_ta_accum_item * ) calloc(1, sizeof( mm_ta_accum_item ) );
199 memset( accum, 0, sizeof (mm_ta_accum_item) );
200 accum->elapsed_min = MAX_UINT64;
202 accum->name = strdup(name);
204 g_accums[g_accum_index] = accum;
207 if ( g_accum_longest_name < name_len )
208 g_accum_longest_name = name_len;
213 accum = g_accums[index];
216 // verify pairs of begin, end.
217 if (accum->on_estimate)
219 MyPrintf("[%s] is not 'end'ed!\n", accum->name);
220 accum->num_unpair ++;
224 accum->on_estimate = 1;
227 gettimeofday( &t, NULL );
228 accum->timestamp = t.tv_sec * 1000000UL + t.tv_usec;
230 if ( accum->first_start == 0 )
231 { // assum that timestamp never could be zero.
232 accum->first_start = accum->timestamp;
234 if ( g_accum_first_time > accum->first_start )
236 g_accum_first_time = accum->first_start ;
241 MyPrintf("[ACCUM BEGIN] %s : %ld ---(%s:%d)\n", name, accum->timestamp, filename, line );
248 int mm_ta_accum_item_end(const char* name, bool show, const char* filename, int line)
250 mm_ta_accum_item * accum = NULL;
251 unsigned long long tval = 0LL;
258 if ( g_accum_index == MM_TA_MAX_ACCUM )
264 if( strlen ( name ) == 0 )
267 // varify the 'name' is already exist.
268 if ( (index = __get_accum_index(name)) == -1 )
270 MyPrintf("[%s] is not added before!\n", name);
274 accum = g_accums[index];
276 // verify pairs of begin, end.
277 if (!accum->on_estimate)
279 MyPrintf("[%s] is not 'begin' yet!\n", accum->name);
280 accum->num_unpair ++;
284 // get time first for more accuracy.
285 gettimeofday( &t, NULL );
286 tval = t.tv_sec*1000000UL + t.tv_usec;
289 accum->last_end = tval;
292 if ( accum->first_start > accum->last_end )
294 MyPrintf("Invalied timestamp:%s. Start:%lu End=%lu\n", accum->name, accum->first_start , accum->last_end);
298 // make get elapsed time.
299 tval = tval - accum->timestamp;
302 accum->elapsed_max = tval > accum->elapsed_max ? tval : accum->elapsed_max;
303 accum->elapsed_min = tval < accum->elapsed_min ? tval : accum->elapsed_min;
306 MyPrintf("[ACCUM END] %s : %llu + %llu ---(%s:%d)\n", name, accum->elapsed_accum, tval, filename, line );
309 accum->elapsed_accum = accum->elapsed_accum + tval;
310 accum->on_estimate = 0;
315 void __print_some_info(FILE* fp)
320 // General infomation
323 char hostname[256] = {'\0',};
326 struct rusage r_usage;
328 fprintf(fp, "\n[[ General info ]]\n");
332 fprintf(fp, "Date : %s", ctime(&t_val) );
335 if ( gethostname(hostname, 255) == 0 )
337 fprintf(fp, "Hostname : %s\n", hostname);
340 if ( uname(&uts) >= 0 )
342 fprintf(fp, "System : %s\n", uts.sysname);
343 fprintf(fp, "Machine : %s\n", uts.machine);
344 fprintf(fp, "Nodename : %s\n", uts.nodename);
345 fprintf(fp, "Release : %s \n", uts.release);
346 fprintf(fp, "Version : %s \n", uts.version);
350 fprintf(fp, "Process priority : %d\n", getpriority(PRIO_PROCESS, getpid()) );
352 getrusage(RUSAGE_SELF, &r_usage);
353 fprintf(fp, "CPU usage : User = %ld.%06ld, System = %ld.%06ld\n",
354 r_usage.ru_utime.tv_sec, r_usage.ru_utime.tv_usec,
355 r_usage.ru_stime.tv_sec, r_usage.ru_stime.tv_usec );
360 // host environment variables
362 extern char** environ;
363 char** env = environ;
365 fprintf(fp, "\n[[ Host environment variables ]]\n");
368 fprintf(fp, "%s\n", *env);
373 fprintf(fp, "g_accum_first_time = %llu\n", g_accum_first_time);
380 void mm_ta_accum_show_result_fp(FILE *fp)
385 // __print_some_info(fp);
388 fprintf(fp, "============================ BEGIN RESULT ACCUM (usec) ====================\n");
390 snprintf(format, (size_t)sizeof(format), "[Idx] %%-%ds %%10s %%6s %%10s %%10s %%10s %%4s \n", g_accum_longest_name);
392 fprintf(fp, format, "Name", "avg", "hit", "total", "min", "max", "pair");
394 snprintf(format, (size_t)sizeof(format), "[%%3d] %%-%ds %%10llu %%6lu %%10llu %%10llu %%10llu %%4s \n", g_accum_longest_name);
396 for ( i = 0; i < g_accum_index; i++ )
398 // prevent 'devide by zero' error
399 if (g_accums[i]->num_calls == 0)
400 g_accums[i]->num_calls = 1;
406 (g_accums[i]->elapsed_accum == 0)?0:(g_accums[i]->elapsed_accum / g_accums[i]->num_calls), // Fix it! : devide by zero.
407 g_accums[i]->num_calls,
408 g_accums[i]->elapsed_accum,
409 g_accums[i]->elapsed_min,
410 g_accums[i]->elapsed_max,
411 g_accums[i]->num_unpair == 1 ? "F" : "T" );
414 fprintf(fp, "============================ END RESULT ACCUM ============================\n");
416 if ( fp != stdout && fp != stderr )
423 #define _CONSTRUCTOR __attribute__ ((constructor))
424 #define _DESTRUCTOR __attribute__ ((destructor))
426 static void _CONSTRUCTOR _DLLInit(void)
431 static void _DESTRUCTOR _DLLExit(void)
439 int main(int argc, char* argv[])
444 PERF_CHECK_BEGIN("Test 1");
446 for ( a = 0 ; a < 10; a++)
448 printf("AAA=%d\n", a);
452 PERF_CHECK_END("Test 1");
454 printf("Test 111\n");