float get_energy() { static unsigned long int count = 0; int prev = !curr; /* Don't buffer data if redirected to a pipe */ //setbuf(stdout, NULL); memset(&sys_stats[curr], 0, SYS_INFO_SIZE); read_process_stats(curr); read_cpufreq_stats(&sys_stats[curr]); u32 delta_runtime = subcount(sys_stats[curr].runtime, sys_stats[prev].runtime); float delta_cpu = (u64_subcount(sys_stats[curr].stats.utime, sys_stats[prev].stats.utime) + u64_subcount(sys_stats[curr].stats.stime, sys_stats[prev].stats.stime)) * (100.0f / delta_runtime); u32 delta_itv = u64_subcount(sys_stats[curr].itv, sys_stats[prev].itv); stm_time_t delta_timestamp = u64_subcount(sys_stats[curr].timestamp, sys_stats[prev].timestamp); /* (avg cpu time) * (cpu power) * (run percent) / 100 */ double power = delta_cpu * sys_stats[curr].cpupower * (delta_runtime * 1.0f / delta_itv) / 100.0f; if (power != power) // check not NaN { #ifdef POWER_DEBUG DEBUG(stdout, "NaN result\n"); #endif power = 0; } power_history[power_index].power = power; power_history[power_index].delta = delta_timestamp; /* timestamp set as last element to avoid critical raise in CPUEnergy */ power_history[power_index].timestamp = sys_stats[curr].timestamp; #ifdef POWER_DEBUG DEBUG(stdout, "[%lu - %d/%d] Power %f @ %llu for %f\n", count, power_index, RETENTION_SIZE, power_history[power_index].power, power_history[power_index].timestamp, power_history[power_index].delta / 1000000.0f); #endif if(count > 0 && !power) { #ifdef POWER_ALERT WARNING(stdout, "Power consumption read 0 W, the acquiring interval '%f msec' is too small. Start: %llu, End: %llu, delta: %f\n", (float)ACQUIRING_INTERVAL, sys_stats[prev].timestamp, sys_stats[curr].timestamp, delta_timestamp / 1000000.0); #endif } else { power_index = NEXT_RETENTION_SIZE(power_index); curr ^= 1; } count++; return power; }
int main(int argc, char *argv[]) { struct latency_entry *e; int delay, iterations; int pid, tid; int count, erase; int i; delay = 1; iterations = 0; pid = tid = 0; for (i = 1; i < argc; i++) { if (!strcmp(argv[i], "-d")) { if (i >= argc - 1) { fprintf(stderr, "Option -d expects an argument.\n"); exit(EXIT_FAILURE); } delay = atoi(argv[++i]); continue; } if (!strcmp(argv[i], "-n")) { if (i >= argc - 1) { fprintf(stderr, "Option -n expects an argument.\n"); exit(EXIT_FAILURE); } iterations = atoi(argv[++i]); continue; } if (!strcmp(argv[i], "-h")) { usage(argv[0]); exit(EXIT_SUCCESS); } if (!strcmp(argv[i], "-p")) { if (i >= argc - 1) { fprintf(stderr, "Option -p expects an argument.\n"); exit(EXIT_FAILURE); } pid = atoi(argv[++i]); continue; } if (!strcmp(argv[i], "-t")) { if (i >= argc - 1) { fprintf(stderr, "Option -t expects an argument.\n"); exit(EXIT_FAILURE); } tid = atoi(argv[++i]); continue; } fprintf(stderr, "Invalid argument \"%s\".\n", argv[i]); usage(argv[0]); exit(EXIT_FAILURE); } if (tid && !pid) { fprintf(stderr, "If you provide a thread ID with -t, you must provide a process ID with -p.\n"); exit(EXIT_FAILURE); } check_latencytop(); free_entries = NULL; signal(SIGINT, &signal_handler); signal(SIGTERM, &signal_handler); atexit(&disable_latencytop); set_latencytop(1); count = 0; erase = 1; while ((iterations == 0) || (count++ < iterations)) { sleep(delay); e = NULL; if (pid) { if (tid) { e = read_thread_stats(e, erase, pid, tid, 1); } else { e = read_process_stats(e, erase, pid); } } else { e = read_global_stats(e, erase); } erase = 0; clear_screen(); if (pid) { if (tid) { printf("Latencies for thread %d in process %d:\n", tid, pid); } else { printf("Latencies for process %d:\n", pid); } } else { printf("Latencies across all processes:\n"); } print_latency_entries(e); } set_latencytop(0); return 0; }