void operator() (const char * event, T func, long int bytes_read = 0, long int ops = 0, long int bytes_written = 0) { #ifdef CYCLE_PROFILING if (currentevent==maxevents) { func(); } else { const auto countfd = thread_counter_fds.get_counter_fd(); start_counter(countfd); func(); long long cycs = stop_counter(countfd); // Store the profiling data std::lock_guard<std::mutex> lock_events(event_lock); events[currentevent++] = { get_event_id(event), bytes_read, ops, bytes_written, cycs }; } #else (void) event; (void) bytes_read; (void) ops; (void) bytes_written; func(); #endif // CYCLE_PROFILING }
~profiler() { std::lock_guard<std::mutex> lock_events(event_lock); // Compute performance from recorded events struct ProfileResult { ProfileResult() : total_calls(0), total_duration(0), total_bytes_read(0), total_ops(0), total_bytes_written(0) { } void operator+=(const ProfileEntry &rhs) { total_calls++; total_duration += rhs.duration; total_bytes_read += rhs.bytes_read; total_ops += rhs.ops; total_bytes_written = rhs.bytes_written; } float avg_duration(void) const { return static_cast<float>(total_duration) / static_cast<float>(total_calls); } float bytes_read_per_cycle(void) const { return static_cast<float>(total_bytes_read) / static_cast<float>(total_duration); } float ops_per_cycle(void) const { return static_cast<float>(total_ops) / static_cast<float>(total_duration); } float bytes_written_per_cycle(void) const { return static_cast<float>(total_bytes_written) / static_cast<float>(total_duration); } long int total_calls, total_duration, total_bytes_read, total_ops, total_bytes_written; }; std::vector<ProfileResult> totals; totals.resize(event_ids.size()); for (int i = 0; i < currentevent; i++) { const auto &event = events[i]; totals[event.event_id] += event; } // Get the longest label int len_label = 0; for (const auto &kv : event_ids) { len_label = std::max(len_label, static_cast<int>(strlen(kv.first))); } // Get the longest values for every other field const auto get_length_of_field = [totals] (const char *title, auto f, auto len) -> size_t { size_t l = strlen(title); for (const auto &v : totals) { l = std::max(l, len(f(v))); } return l; }; // Get the strlen for an int const auto intlen = [] (long int x) -> size_t { size_t len = 0; do { x /= 10; len++; } while (x); return len; }; // Get the strlen for a float const auto floatlen = [] (const int precision) { return [precision] (float x) { size_t len = 0; if (!std::isfinite(x)) { return static_cast<size_t>(3); } do { x /= 10.0f; len++; } while (x > 1.0f); return len + 1 + precision; }; }; const int len_calls = get_length_of_field( "Calls", [] (const auto &v) {return v.total_calls;}, intlen ); const int len_duration = get_length_of_field( "Duration", [] (const auto &v) {return v.total_duration;}, intlen ); const int len_average_duration = get_length_of_field( "Average", [] (const auto &v) {return v.avg_duration();}, floatlen(2) ); const int len_reads_per_cycle = get_length_of_field( "Reads / cycle", [] (const auto &v) {return v.bytes_read_per_cycle();}, floatlen(6) ); const int len_ops_per_cycle = get_length_of_field( "Ops / cycle", [] (const auto &v) {return v.ops_per_cycle();}, floatlen(6) ); const int len_writes_per_cycle = get_length_of_field( "Writes / cycle", [] (const auto &v) {return v.bytes_written_per_cycle();}, floatlen(6) ); // Print header printf( "%*s %*s %*s %*s %*s %*s %*s\n", len_label, "", len_calls, "Calls", len_duration, "Duration", len_average_duration, "Average", len_reads_per_cycle, "Reads / cycle", len_ops_per_cycle, "Ops / cycle", len_writes_per_cycle, "Writes / cycle" ); for (const auto &kv : event_ids) { const auto id = kv.second; printf( "%*s %*ld %*ld %*.2f %*.6f %*.6f %*.6f\n", len_label, kv.first, len_calls, totals[id].total_calls, len_duration, totals[id].total_duration, len_average_duration, totals[id].avg_duration(), len_reads_per_cycle, totals[id].bytes_read_per_cycle(), len_ops_per_cycle, totals[id].ops_per_cycle(), len_writes_per_cycle, totals[id].bytes_written_per_cycle() ); } printf("\n"); }
GRAPHICS_EVENT *search_single_queue( /*search for event */ INT16 fd, /*queue to search */ INT8 event_type /*type to search for */ ) { GRAPHICS_EVENT *event; /*event from daemon */ GRAPHICS_EVENT *prev; /*previous event */ GRAPHICS_EVENT *event2; /*2nd event */ GRAPHICS_EVENT *prev2; /*2nd previous */ GRAPHICS_EVENT *nextevent; /*next event in list */ BOOL8 any_destroy = FALSE; lock_events(); event_waiting = FALSE; //done a scan prev = NULL; /*previous event */ event2 = NULL; /*2nd event */ if (event_type == ANY_EVENT) { event = sbfds[fd].events; /*start of queue */ } else if (event_type == SELECT_EVENT) { for (prev = NULL, event = sbfds[fd].events; event != NULL && event->type != DOWN_EVENT; event = nextevent) { //Delete up events that are in the list prior to a down event nextevent = event->next; /*next in list */ if (event->type == UP_EVENT) { if (prev == NULL) /*new head */ sbfds[fd].events = nextevent; else prev->next = nextevent;/*delete event */ if (nextevent == NULL) /*new last element */ sbfds[fd].lastevent = prev; delete event; } else prev = event; if (event->type == DESTROY_EVENT) any_destroy = TRUE; } if (event == NULL) { unlock_events(); if (any_destroy) return search_single_queue (fd, DESTROY_EVENT); return NULL; /*no good */ } for (prev2 = event, event2 = event->next; event2 != NULL && event2->type != UP_EVENT; prev2 = event2, event2 = event2->next); if (event2 == NULL) { unlock_events(); return NULL; /*no good */ } if (prev2 != event) { /*got some intervening */ for (prev2 = event->next; prev2 != event2; prev2 = nextevent) { nextevent = prev2->next; delete prev2; } } event->next = event2->next; /*cut out event2 */ event2->next = NULL; /*event is new end */ event->xmax = event2->x; /*get coords */ event->ymax = event2->y; if (event->x > event->xmax) { event->xmax = event->x; event->x = event2->x; /*get coords */ } if (event->y > event->ymax) { event->ymax = event->y; event->y = event2->y; } delete event2; //free the element } else { for (prev = NULL, event = sbfds[fd].events; event != NULL && event->type != DESTROY_EVENT && event->type != event_type; event = nextevent) { nextevent = event->next; /*next in list */ /*delete up in front of down */ if (event->type == UP_EVENT && event_type == DOWN_EVENT) { if (prev == NULL) /*new head */ sbfds[fd].events = nextevent; else prev->next = nextevent;/*delete event */ if (nextevent == NULL) /*new last element */ sbfds[fd].lastevent = prev; delete event; } else prev = event; /*trailing ptr */ } } if (event == NULL) { unlock_events(); return NULL; /*no good */ } if (event->type != DESTROY_EVENT) { if (prev == NULL) /*new head */ sbfds[fd].events = event->next; else prev->next = event->next; /*delete event */ if (event->next == NULL) sbfds[fd].lastevent = prev;/*new last event */ event->next = NULL; /*possible 2nd event */ } unlock_events(); return event; /*got one!! */ }