/************************************************************************** * * Copyright 2015 Alexander Trukhin * All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. * **************************************************************************/ #include #include "metric_writer.hpp" void ProfilerQuery::writeMetricHeaderCallback(Metric* metric, int event, void* data, int error, void* userData) { std::cout << "\t" << metric->name(); } void ProfilerQuery::writeMetricEntryCallback(Metric* metric, int event, void* data, int error, void* userData) { if (error) { std::cout << "\t" << "#ERR" << error; return; } if (!data) { std::cout << "\t" << "-"; return; } switch(metric->numType()) { case CNT_NUM_UINT: std::cout << "\t" << *(reinterpret_cast(data)); break; case CNT_NUM_FLOAT: std::cout << "\t" << *(reinterpret_cast(data)); break; case CNT_NUM_DOUBLE: std::cout << "\t" << *(reinterpret_cast(data)); break; case CNT_NUM_BOOL: std::cout << "\t" << *(reinterpret_cast(data)); break; case CNT_NUM_UINT64: std::cout << "\t" << *(reinterpret_cast(data)); break; case CNT_NUM_INT64: std::cout << "\t" << *(reinterpret_cast(data)); break; } } void ProfilerQuery::writeMetricHeader(QueryBoundary qb) const { for (auto &a : *metricBackends) { a->enumDataQueryId(eventId, &writeMetricHeaderCallback, qb); } std::cout << std::endl; } void ProfilerQuery::writeMetricEntry(QueryBoundary qb) const { for (auto &a : *metricBackends) { a->enumDataQueryId(eventId, &writeMetricEntryCallback, qb); } std::cout << std::endl; } template T ProfilerCall::StringTable::getId(const std::string &str) { auto res = stringLookupTable.find(str); T index; if (res == stringLookupTable.end()) { index = static_cast(strings.size()); strings.push_back(str); stringLookupTable[str] = index; } else { index = res->second; } return index; } template std::string ProfilerCall::StringTable::getString(T id) { return strings[static_cast(id)]; } ProfilerCall::ProfilerCall(unsigned eventId, const data* queryData) : ProfilerQuery(QUERY_BOUNDARY_CALL, eventId) { if (queryData) { isFrameEnd = queryData->isFrameEnd; no = queryData->no; program = queryData->program; nameTableEntry = nameTable.getId(queryData->name); } } void ProfilerCall::writeHeader() const { std::cout << "#\tcall no\tprogram\tname"; ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_CALL); } void ProfilerCall::writeEntry() const { if (isFrameEnd) { std::cout << "frame_end" << std::endl; } else { std::cout << "call" << "\t" << no << "\t" << program << "\t" << nameTable.getString(nameTableEntry); ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_CALL); } } void ProfilerDrawcall::writeHeader() const { std::cout << "#\tcall no\tprogram\tname"; ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_DRAWCALL); } void ProfilerDrawcall::writeEntry() const { if (isFrameEnd) { std::cout << "frame_end" << std::endl; } else { std::cout << "call" << "\t" << no << "\t" << program << "\t" << nameTable.getString(nameTableEntry); ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_DRAWCALL); } } void ProfilerFrame::writeHeader() const { std::cout << "#"; ProfilerQuery::writeMetricHeader(QUERY_BOUNDARY_FRAME); } void ProfilerFrame::writeEntry() const { std::cout << "frame"; ProfilerQuery::writeMetricEntry(QUERY_BOUNDARY_FRAME); } MetricWriter::MetricWriter(std::vector &metricBackends, const MmapAllocator &alloc) : frameQueue(MmapAllocator(alloc)), callQueue(MmapAllocator(alloc)), drawcallQueue(MmapAllocator(alloc)) { ProfilerQuery::metricBackends = &metricBackends; } void MetricWriter::addQuery(QueryBoundary boundary, unsigned eventId, const void* queryData) { switch (boundary) { case QUERY_BOUNDARY_FRAME: frameQueue.emplace_back(eventId); break; case QUERY_BOUNDARY_CALL: callQueue.emplace_back(eventId, reinterpret_cast(queryData)); break; case QUERY_BOUNDARY_DRAWCALL: drawcallQueue.emplace_back(eventId, reinterpret_cast(queryData)); break; default: break; } } void MetricWriter::writeQuery(QueryBoundary boundary) { switch (boundary) { case QUERY_BOUNDARY_FRAME: frameQueue.front().writeEntry(); frameQueue.pop_front(); break; case QUERY_BOUNDARY_CALL: callQueue.front().writeEntry(); callQueue.pop_front(); break; case QUERY_BOUNDARY_DRAWCALL: drawcallQueue.front().writeEntry(); drawcallQueue.pop_front(); break; default: break; } } void MetricWriter::writeAll(QueryBoundary boundary) { switch (boundary) { case QUERY_BOUNDARY_FRAME: frameQueue.front().writeHeader(); while (!frameQueue.empty()) { writeQuery(boundary); } break; case QUERY_BOUNDARY_CALL: callQueue.front().writeHeader(); while (!callQueue.empty()) { writeQuery(boundary); } break; case QUERY_BOUNDARY_DRAWCALL: drawcallQueue.front().writeHeader(); while (!drawcallQueue.empty()) { writeQuery(boundary); } break; default: break; } std::cout << std::endl; } std::vector* ProfilerQuery::metricBackends = nullptr; ProfilerCall::StringTable ProfilerCall::nameTable;