2017-04-01 11:10:38 -07:00
|
|
|
#include "zprofiling.h"
|
|
|
|
|
|
|
|
#ifdef VOXEL_PROFILING
|
2018-09-19 12:25:04 -07:00
|
|
|
#include <core/os/os.h>
|
2020-01-02 12:23:36 -08:00
|
|
|
#include <fstream>
|
2020-01-07 12:32:36 -08:00
|
|
|
#include <sstream>
|
|
|
|
#include <thread>
|
|
|
|
#include <unordered_map>
|
2020-01-02 12:23:36 -08:00
|
|
|
|
|
|
|
namespace {
|
2020-01-07 12:32:36 -08:00
|
|
|
thread_local ZProfiler g_profiler;
|
2020-01-02 12:23:36 -08:00
|
|
|
}
|
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
ZProfiler &ZProfiler::get_thread_profiler() {
|
2020-01-02 12:23:36 -08:00
|
|
|
return g_profiler;
|
|
|
|
}
|
|
|
|
|
2017-04-01 11:10:38 -07:00
|
|
|
inline uint64_t get_time() {
|
|
|
|
return OS::get_singleton()->get_ticks_usec();
|
|
|
|
}
|
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
ZProfiler::ZProfiler() {
|
2020-01-07 12:32:36 -08:00
|
|
|
std::stringstream ss;
|
|
|
|
ss << std::this_thread::get_id();
|
|
|
|
_profiler_name = ss.str();
|
2019-08-18 15:13:12 -07:00
|
|
|
for (int i = 0; i < _pages.size(); ++i) {
|
|
|
|
_pages[i] = new Page();
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
ZProfiler::~ZProfiler() {
|
|
|
|
dump();
|
|
|
|
for (int i = 0; i < _pages.size(); ++i) {
|
|
|
|
delete _pages[i];
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
void ZProfiler::set_profiler_name(std::string name) {
|
2019-08-18 15:13:12 -07:00
|
|
|
_profiler_name = name;
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
void ZProfiler::begin(const char *description) {
|
|
|
|
Event e;
|
|
|
|
e.description = description;
|
|
|
|
e.type = EVENT_PUSH;
|
|
|
|
e.time = get_time();
|
|
|
|
push_event(e);
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
void ZProfiler::end() {
|
|
|
|
Event e;
|
|
|
|
e.description = nullptr;
|
|
|
|
e.type = EVENT_POP;
|
|
|
|
e.time = get_time();
|
|
|
|
push_event(e);
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
void ZProfiler::push_event(Event e) {
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
if (_current_page < _pages.size()) {
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
Page &page = *_pages[_current_page];
|
|
|
|
page.events[page.write_index] = e;
|
|
|
|
++page.write_index;
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
if (page.write_index >= page.events.size()) {
|
|
|
|
++_current_page;
|
|
|
|
if (_current_page >= _pages.size()) {
|
2020-01-07 12:32:36 -08:00
|
|
|
printf("ZProfiler end of capacity\n");
|
2019-08-18 15:13:12 -07:00
|
|
|
}
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
void ZProfiler::dump() {
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
printf("Dumping ZProfiler data\n");
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
unsigned short next_index = 1;
|
2020-01-07 12:32:36 -08:00
|
|
|
std::unordered_map<const char *, unsigned short> string_index;
|
2019-08-18 15:13:12 -07:00
|
|
|
|
|
|
|
for (int i = 0; i < _pages.size(); ++i) {
|
|
|
|
const Page &page = *_pages[i];
|
|
|
|
|
|
|
|
for (int j = 0; j < page.events.size(); ++j) {
|
|
|
|
const Event &event = page.events[j];
|
|
|
|
|
|
|
|
if (event.description == nullptr) {
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
auto it = string_index.find(event.description);
|
|
|
|
if (it == string_index.end()) {
|
|
|
|
string_index.insert(std::make_pair(event.description, next_index));
|
2019-08-18 15:13:12 -07:00
|
|
|
++next_index;
|
|
|
|
}
|
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
std::ofstream ofs(_profiler_name + "_profiling_data.bin", std::ios::out | std::ios::binary | std::ios::trunc);
|
|
|
|
ERR_FAIL_COND(!ofs.good());
|
2019-08-18 15:13:12 -07:00
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
uint16_t string_index_size = string_index.size();
|
|
|
|
ofs.write((char *)&string_index_size, sizeof(uint16_t));
|
2019-08-18 15:13:12 -07:00
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
for (auto it = string_index.begin(); it != string_index.end(); ++it) {
|
2020-01-02 12:23:36 -08:00
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
const char *key = it->first;
|
|
|
|
uint16_t p = it->second;
|
|
|
|
uint32_t len = std::strlen(key);
|
2020-01-02 12:23:36 -08:00
|
|
|
|
2020-01-07 12:32:36 -08:00
|
|
|
ofs.write((char *)&p, sizeof(uint16_t));
|
|
|
|
ofs.write((char *)&len, sizeof(uint32_t));
|
|
|
|
ofs.write(key, len);
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
int page_count = _current_page + 1;
|
|
|
|
if (page_count >= _pages.size()) {
|
|
|
|
page_count = _pages.size();
|
|
|
|
}
|
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
int level = 0;
|
|
|
|
uint32_t last_time = 0;
|
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
for (int i = 0; i < page_count; ++i) {
|
|
|
|
const Page &page = *_pages[i];
|
2017-04-01 11:10:38 -07:00
|
|
|
|
2019-08-18 15:13:12 -07:00
|
|
|
for (int j = 0; j < page.write_index; ++j) {
|
|
|
|
const Event &event = page.events[j];
|
2020-01-02 12:23:36 -08:00
|
|
|
last_time = event.time;
|
|
|
|
|
|
|
|
if (event.type == EVENT_PUSH) {
|
|
|
|
++level;
|
|
|
|
} else if (event.type == EVENT_POP) {
|
|
|
|
if (level > 0) {
|
|
|
|
--level;
|
|
|
|
} else {
|
|
|
|
printf("ZProfiler: unexpected pop\n");
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
CRASH_COND(true);
|
|
|
|
}
|
2019-08-18 15:13:12 -07:00
|
|
|
|
|
|
|
unsigned short desc_index = 0;
|
|
|
|
if (event.description != nullptr) {
|
2020-01-07 12:32:36 -08:00
|
|
|
desc_index = string_index[event.description];
|
2019-08-18 15:13:12 -07:00
|
|
|
}
|
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
ofs.write((char *)&event.time, sizeof(uint32_t));
|
|
|
|
ofs.write((char *)&event.type, sizeof(uint8_t));
|
|
|
|
ofs.write((char *)&desc_index, sizeof(uint16_t));
|
2019-08-18 15:13:12 -07:00
|
|
|
}
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
2019-08-18 15:13:12 -07:00
|
|
|
|
2020-01-02 12:23:36 -08:00
|
|
|
while (level > 0) {
|
|
|
|
printf("ZProfiler: filling missing pop\n");
|
|
|
|
|
|
|
|
uint32_t time = last_time + 1;
|
|
|
|
uint8_t type = EVENT_POP;
|
|
|
|
uint16_t desc_index = 0;
|
|
|
|
|
|
|
|
ofs.write((char *)&time, sizeof(uint32_t));
|
|
|
|
ofs.write((char *)&type, sizeof(uint8_t));
|
|
|
|
ofs.write((char *)&desc_index, sizeof(uint16_t));
|
|
|
|
|
|
|
|
--level;
|
|
|
|
}
|
|
|
|
|
|
|
|
ofs.close();
|
2017-04-01 11:10:38 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
#endif // VOXEL_PROFILING
|