Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
158 changes: 121 additions & 37 deletions include/ctrack.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,12 +255,30 @@ namespace ctrack {
stream << "\n";
}

template<typename StreamType>
void csvRow(StreamType& stream, const std::vector<std::string>& row) const {
for (size_t i = 0; i < row.size(); ++i) {
stream << row[i];
if (i < row.size() - 1) {
stream << ",";
}
}
stream << "\n";
}

public:
BeautifulTable(const std::vector<std::string>& headerColumns, bool enableColor = false, const ColorScheme& colors = default_colors, const std::vector<std::pair<std::string, int>>& top_header = {})
: header(headerColumns), useColor(enableColor), colors(colors), top_header(top_header) {
updateColumnWidths(header);
}

enum class ResultFormat {
TABLE,
CSV,
JSON,
DB
};

void addRow(const std::vector<std::string>& row) {
if (row.size() != header.size()) {
throw std::invalid_argument("Row size must match header size");
Expand All @@ -269,6 +287,23 @@ namespace ctrack {
updateColumnWidths(row);
}

template<typename StreamType>
void output(StreamType& stream, BeautifulTable::ResultFormat resultFormat) const {
switch (resultFormat) {
case BeautifulTable::ResultFormat::TABLE:
print(stream);
break;
case BeautifulTable::ResultFormat::CSV:
csv(stream);
break;
case BeautifulTable::ResultFormat::JSON:
case BeautifulTable::ResultFormat::DB:
default:
std::cerr << "Invalid choice, DB and JSON not yet supported." << std::endl;
break;
}
}

template<typename StreamType>
void print(StreamType& stream) const {
if (top_header.size() > 0) {
Expand All @@ -284,42 +319,64 @@ namespace ctrack {
}
}

template<typename StreamType>
void csv(StreamType& stream) const {
if (top_header.size() > 0) {
// csvRow(stream, top_header);
}
csvRow(stream, header);
for (const auto& row : rows) {
csvRow(stream, row);
}
}

template<typename T>
static inline std::string table_string(const T& value) {
std::ostringstream oss;
oss << value;
return oss.str();
}

static inline std::string table_time(uint_fast64_t nanoseconds) {
return table_time(static_cast<double>(nanoseconds));
static inline std::string table_time(uint_fast64_t nanoseconds, bool add_unit = true) {
return table_time(static_cast<double>(nanoseconds), add_unit);
}

static inline std::string table_time(double nanoseconds) {
const char* units[] = { "ns", "mcs", "ms", "s" };
static inline std::string table_time(double nanoseconds, bool add_unit = true) {
constexpr std::string_view units[] = { "ns", "mcs", "ms", "s" };
int unit = 0;
double value = static_cast<double>(nanoseconds);
while (value >= 1000 && unit < 3) {
value /= 1000;
unit++;
}
std::ostringstream oss;
oss << std::fixed << std::setprecision(2) << value << " " << units[unit];
oss << std::fixed << std::setprecision(2) << value;

if (add_unit) {
oss << " " << units[unit];
}
return oss.str();
}

static inline std::string table_percentage(uint_fast64_t value, uint_fast64_t total) {
if (total == 0) {
static inline std::string table_percentage(uint_fast64_t value, uint_fast64_t total, bool add_unit = true) {
if (total == 0 && add_unit) {
return "nan%";
}

if (total == 0 && !add_unit) {
return "nan";
}

// Calculate the percentage
double percentage = (static_cast<double>(value) / total) * 100.0;

// Format the percentage as a string with 2 decimal places
std::ostringstream ss;
ss << std::fixed << std::setprecision(2) << percentage << "%";
ss << std::fixed << std::setprecision(2) << percentage;

if (add_unit) {
ss << "%";
}
return ss.str();
}

Expand Down Expand Up @@ -656,52 +713,73 @@ namespace ctrack {
};

template<typename StreamType>
void get_summary_table(StreamType& stream, bool use_color = false) {
void get_summary(StreamType& stream, bool use_color = false, BeautifulTable::ResultFormat resultFormat = BeautifulTable::ResultFormat::TABLE) {

bool add_unit = resultFormat == BeautifulTable::ResultFormat::TABLE;

BeautifulTable info({ "Start","End","time total","time ctracked","time ctracked %", }, use_color, alternate_colors);
info.addRow({ BeautifulTable::table_timepoint(track_start_time), BeautifulTable::table_timepoint(track_end_time),
BeautifulTable::table_time(time_total), BeautifulTable::table_time(sum_time_active_exclusive),
BeautifulTable::table_percentage(sum_time_active_exclusive, time_total)
});
info.addRow({
BeautifulTable::table_timepoint(track_start_time),
BeautifulTable::table_timepoint(track_end_time),
BeautifulTable::table_time(time_total, add_unit),
BeautifulTable::table_time(sum_time_active_exclusive, add_unit),
BeautifulTable::table_percentage(sum_time_active_exclusive, time_total, add_unit)
});

info.output(stream, resultFormat);

info.print(stream);
BeautifulTable table({ "filename", "function", "line","calls","ae" + center_intervall_str + "%","ae[0-100]%",
"time ae[0-100]" ,"time a[0-100]" }, use_color, alternate_colors);
"time ae[0-100]" ,"time a[0-100]" }, use_color, alternate_colors);
for (auto& entry : sorted_events) {
table.addRow({ BeautifulTable::stable_shortenPath(entry->filename), entry->function_name,BeautifulTable::table_string(entry->line),
table.addRow({
BeautifulTable::stable_shortenPath(entry->filename), entry->function_name,
BeautifulTable::table_string(entry->line),
BeautifulTable::table_string(entry->all_cnt),
BeautifulTable::table_percentage(entry->center_time_active_exclusive, time_total),
BeautifulTable::table_percentage(entry->all_time_active_exclusive,time_total),
BeautifulTable::table_time(entry->all_time_active_exclusive),
BeautifulTable::table_time(entry->all_time_active) });
BeautifulTable::table_percentage(entry->center_time_active_exclusive, time_total, add_unit),
BeautifulTable::table_percentage(entry->all_time_active_exclusive, time_total, add_unit),
BeautifulTable::table_time(entry->all_time_active_exclusive, add_unit),
BeautifulTable::table_time(entry->all_time_active, add_unit) });
}

table.print(stream);
table.output(stream, resultFormat);
};

template<typename StreamType>
void get_detail_table(StreamType& stream, bool use_color = false, bool reverse_vector = false) {
void get_detail(StreamType& stream, bool use_color = false, bool reverse_vector = false, BeautifulTable::ResultFormat resultFormat = BeautifulTable::ResultFormat::TABLE) {

bool add_unit = resultFormat == BeautifulTable::ResultFormat::TABLE;

if (reverse_vector) {
std::reverse(sorted_events.begin(), sorted_events.end());
}
for (int i = static_cast<int>(sorted_events.size()) - 1; i >= 0; i--) {
auto& entry = sorted_events[i];

BeautifulTable info({ "filename", "function", "line","time acc","sd","cv","calls","threads" }, use_color, default_colors);
info.addRow({ BeautifulTable::stable_shortenPath(entry->filename), entry->function_name,BeautifulTable::table_string(entry->line),
BeautifulTable::table_time(entry->all_time_acc),
BeautifulTable::table_time(sorted_events[i]->all_st),BeautifulTable::table_string(sorted_events[i]->all_cv),
BeautifulTable::table_string(sorted_events[i]->all_cnt), BeautifulTable::table_string(sorted_events[i]->all_thread_cnt) });
info.addRow({
BeautifulTable::stable_shortenPath(entry->filename), entry->function_name,
BeautifulTable::table_string(entry->line),
BeautifulTable::table_time(entry->all_time_acc, add_unit),
BeautifulTable::table_time(sorted_events[i]->all_st, add_unit),
BeautifulTable::table_string(sorted_events[i]->all_cv),
BeautifulTable::table_string(sorted_events[i]->all_cnt),
BeautifulTable::table_string(sorted_events[i]->all_thread_cnt) });

BeautifulTable table({ "min", "mean", "min","mean","med","time a","time ae","max","mean","max" }, use_color, default_colors,
{ {"fastest[0-" + std::to_string(settings.non_center_percent) + "]%",2},{"center" + center_intervall_str + "%",6},
{"slowest[" + std::to_string(100 - settings.non_center_percent) + "-100]%",2} });

table.addRow({ BeautifulTable::table_time(entry->fastest_min),BeautifulTable::table_time(entry->fastest_mean),
BeautifulTable::table_time(entry->center_min),BeautifulTable::table_time(entry->center_mean),
BeautifulTable::table_time(entry->center_med),BeautifulTable::table_time(entry->center_time_active),
BeautifulTable::table_time(entry->center_time_active_exclusive),
BeautifulTable::table_time(entry->center_max),
BeautifulTable::table_time(entry->slowest_mean),BeautifulTable::table_time(entry->slowest_max) });
table.addRow({
BeautifulTable::table_time(entry->fastest_min, add_unit),
BeautifulTable::table_time(entry->fastest_mean, add_unit),
BeautifulTable::table_time(entry->center_min, add_unit),
BeautifulTable::table_time(entry->center_mean, add_unit),
BeautifulTable::table_time(entry->center_med, add_unit),
BeautifulTable::table_time(entry->center_time_active, add_unit),
BeautifulTable::table_time(entry->center_time_active_exclusive, add_unit),
BeautifulTable::table_time(entry->center_max, add_unit),
BeautifulTable::table_time(entry->slowest_mean, add_unit),
BeautifulTable::table_time(entry->slowest_max, add_unit) });

info.print(stream);
table.print(stream);
Expand Down Expand Up @@ -928,18 +1006,24 @@ namespace ctrack {
inline void result_print(ctrack_result_settings settings = {}) {
auto res = calc_stats_and_clear(settings);
std::cout << "Details" << std::endl;
res.get_detail_table(std::cout, true);
res.get_detail(std::cout, true);
std::cout << "Summary" << std::endl;
res.get_summary_table(std::cout, true);
res.get_summary(std::cout, true);
}

inline void result_csv(ctrack_result_settings settings = {}, const std::filesystem::path& path = std::filesystem::path("result.csv")) {
auto res = calc_stats_and_clear(settings);
res.get_summary(std::cout, false, BeautifulTable::ResultFormat::CSV);
// TODO write to file
}

inline std::string result_as_string(ctrack_result_settings settings = {}) {
auto res = calc_stats_and_clear(settings);
std::stringstream ss;
ss << "Summary\n";
res.get_summary_table(ss, false);
res.get_summary(ss, false);
ss << "Details\n";
res.get_detail_table(ss, false, true);
res.get_detail(ss, false, true);

return ss.str();
}
Expand Down Expand Up @@ -984,4 +1068,4 @@ namespace ctrack {
#define CTRACK_NAME(name)
#endif // CTRACK_DISABLE

#endif
#endif