// This is larger than the maximum length of a possible line.
constexpr size_t kBufferLen = 256;
bool FillInEntryFromString(const std::string& line, Entry& entry, std::string& error) { // All lines have this format: // TID: ALLOCATION_TYPE POINTER [START_TIME_NS END_TIME_NS] // where // TID is the thread id of the thread doing the operation. // ALLOCATION_TYPE is one of malloc, calloc, memalign, realloc, free, thread_done // POINTER is the hex value of the actual pointer // START_TIME_NS is the start time of the operation in nanoseconds. // END_TIME_NS is the end time of the operation in nanoseconds. // The START_TIME_NS and END_TIME_NS are optional parameters, either both // are present are neither are present. int op_prefix_pos = 0; char name[128]; if (sscanf(line.c_str(), "%d: %127s %" SCNx64 " %n", &entry.tid, name, &entry.ptr,
&op_prefix_pos) != 3) {
error = "Failed to process line: " + line; returnfalse;
}
// Handle each individual type of entry type.
std::string type(name); if (type == "thread_done") { // TID: thread_done 0x0 [END_TIME_NS] // Where END_TIME_NS is optional.
entry.type = THREAD_DONE;
entry.start_ns = 0; // Thread done has an optional time which is when the thread ended. // This is the only entry type that has a single timestamp. int n_match = sscanf(&line[op_prefix_pos], " %" SCNd64, &entry.end_ns);
entry.start_ns = 0; if (n_match == EOF) {
entry.end_ns = 0;
} elseif (n_match != 1) {
error = "Failed to read thread_done end time: " + line; returnfalse;
} returntrue;
}
// Get the optional timestamps if they exist.
args = &args[args_offset]; int n_match =
sscanf(args, "%" SCNd64 " %" SCNd64 "%n", &entry.start_ns, &entry.end_ns, &args_offset); if (n_match == EOF) { returntrue;
}
if (n_match != 2) {
error = "Failed to read timestamps: " + line; returnfalse;
}
// Get the optional present bytes if it exists. if (read_present_bytes) {
n_match = sscanf(&args[args_offset], "%" SCNd64, &entry.present_bytes); if (n_match != EOF && n_match != 1) {
error = "Failed to read present bytes: " + line; returnfalse;
}
} returntrue;
}
constchar* TypeToName(const TypeEnum type) { switch (type) { case CALLOC: return"calloc"; case FREE: return"free"; case MALLOC: return"malloc"; case MEMALIGN: return"memalign"; case REALLOC: return"realloc"; case THREAD_DONE: return"thread_done"; default: return"unknown";
}
}
static size_t FormatEntry(const Entry& entry, char* buffer, size_t buffer_len) { int len = snprintf(buffer, buffer_len, "%d: %s 0x%" PRIx64, entry.tid, TypeToName(entry.type),
entry.ptr); if (len < 0) { return0;
}
size_t cur_len = len; bool output_present_bytes = false; switch (entry.type) { case FREE:
len = 0; if (entry.present_bytes != -1) {
output_present_bytes = true;
} break; case CALLOC:
len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRIu64 " %zu", entry.u.n_elements,
entry.size); break; case MALLOC:
len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %zu", entry.size); break; case MEMALIGN:
len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRIu64 " %zu", entry.u.align,
entry.size); break; case REALLOC:
len = snprintf(&buffer[cur_len], buffer_len - cur_len, " 0x%" PRIx64 " %zu", entry.u.old_ptr,
entry.size); if (entry.present_bytes != -1) {
output_present_bytes = true;
} break; case THREAD_DONE: // Thread done only has a single optional timestamp, end_ns. if (entry.end_ns != 0) {
len = snprintf(&buffer[cur_len], buffer_len - cur_len, " %" PRId64, entry.end_ns); if (len < 0) { return0;
} return cur_len + len;
} return cur_len; default: return0;
} if (len < 0) { return0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.