#help_index "Debugging/Profiler;Profiler;Cmd Line (Typically)/Profiler" #help_file "::/Doc/Profiler" #define PF_ARRAY_COUNT 0x100000 I64 pf_jiffy_start, pf_jiffy_end; I64 *pf_array = NULL; I64 pf_cpu = 0; I64 pf_buf_in_ptr = 0, pf_depth; I64 pf_prof_active = 0; U0 ProfTimerInt(CTask *task) {//See profiler_timer_irq. I64 i, k; if (Bt(&pf_prof_active, 0)) for (k = 0; k <= pf_depth; k++) { if (task == Gs->idle_task) i = SYS_IDLE_PT; else i = TaskCaller(task, k, TRUE); if (pf_buf_in_ptr < PF_ARRAY_COUNT) { pf_array[pf_buf_in_ptr++] = i; pf_jiffy_end = counts.jiffies; } } } public U0 Prof(I64 depth=0, I64 cpu_num=0) {/*Start collecting profiler statistics. Profilers report where time is spent by sampling RIP during the 1000Hz timer interrupt. Do a ProfRep(), (profiler report) after you have collected data. */ if (!(0 <= cpu_num < mp_count)) ST_ERR_ST "Invalid CPU\n"; else { cpu_structs[pf_cpu].profiler_timer_irq = NULL; pf_cpu = cpu_num; pf_depth = depth; pf_buf_in_ptr = 0; if (!pf_array) pf_array = SysMAlloc(sizeof(I64) * PF_ARRAY_COUNT); pf_jiffy_end = pf_jiffy_start = counts.jiffies; LBts(&pf_prof_active, 0); cpu_structs[pf_cpu].profiler_timer_irq = &ProfTimerInt; } } I64 ProfCompare(U8 *i1, U8 *i2) { // Sort Profiler function pointer array by least-->greatest. return i1 - i2; } U0 ProfSort(I64 *array, I64 count) { I64 v1, v2, i1, i2, start_i1, start_i2, end_i1, end_i2, j; while (TRUE) { start_i1 = i1 = 0; profsort_walk: v1 = array[i1]; while (v1 == array[i1]) { end_i1 = i1; start_i2 = i2 = ++i1; } if (i1 > count) break; // bail if first search went out of bounds v2 = array[i2]; while (v2 == array[i2]) end_i2 = i2++; if (i2 > count) break; // bail if second search went out of bounds if (end_i1 - start_i1 > end_i2 - start_i2) { for (j = start_i1; j <= start_i1 + end_i2 - start_i2; j++) array[j] = v2; for (j = start_i1 + end_i2 - start_i2 + 1; j <= end_i2 - start_i2 + end_i1 + 1; j++) array[j] = v1; } else { start_i1 = i1 = start_i2; goto profsort_walk; } } } public U0 ProfRep(I64 filter_count=1, Bool leave_it=OFF) {//Profiler report. Call Prof() first and collect data. I64 i, hits, rip, last_rip = 0, routine_total = 0; F64 total_time; U8 buf[256], buf2[256], last_buf[256]; if (!LBtr(&pf_prof_active, 0)) "Profiler Not Active\n"; if (!pf_buf_in_ptr) "No Profiler Statistic\n"; else { if (!(total_time = pf_jiffy_end - pf_jiffy_start)) total_time = 1; QuickSortI64(pf_array, pf_buf_in_ptr, &ProfCompare); ProfSort(pf_array, pf_buf_in_ptr); *last_buf = 0; "$LTCYAN$ %%Time Hits: &Function+Offset$FG$\n"; for (i = 0; i < pf_buf_in_ptr; i += hits) { rip = pf_array[i]; hits = 0; do hits++; while (i + hits < pf_buf_in_ptr && pf_array[i + hits] == rip); StrPrint(buf, "%p", rip); StrFirstRemove(buf, "+", buf2); if (StrCompare(buf2, last_buf)) { // if (*last_buf && routine_total >= filter_count) // "$GREEN$%6.2f %08X:%s\n$FG$", 100 * routine_total / total_time, routine_total, last_buf; StrCopy(last_buf, buf2); routine_total = 0; } routine_total += hits; if (hits >= filter_count) { "%6.2f %08X:%P\n", 100 * hits / total_time, hits, rip; last_rip = rip; } } // if (*last_buf && routine_total >= filter_count) // "$GREEN$%6.2f %08X:%s\n$FG$", 100 * routine_total / total_time, routine_total, last_buf; "$LTCYAN$ %%Time Hits: &Function+Offset$FG$\n"; "Total Time:%0.6fs\n", total_time / JIFFY_FREQ; if (leave_it) { cpu_structs[pf_cpu].profiler_timer_irq = &ProfTimerInt; LBts(&pf_prof_active, 0); } else cpu_structs[pf_cpu].profiler_timer_irq = NULL; } }