blob: e923ed1d3bd7b5cca032efd7eaaba1c500bafb68 [file] [log] [blame]
/**************************************************************************
*
* 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 <iostream>
#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<unsigned*>(data)); break;
case CNT_NUM_FLOAT: std::cout << "\t" << *(reinterpret_cast<float*>(data)); break;
case CNT_NUM_DOUBLE: std::cout << "\t" << *(reinterpret_cast<double*>(data)); break;
case CNT_NUM_BOOL: std::cout << "\t" << *(reinterpret_cast<bool*>(data)); break;
case CNT_NUM_UINT64: std::cout << "\t" << *(reinterpret_cast<uint64_t*>(data)); break;
case CNT_NUM_INT64: std::cout << "\t" << *(reinterpret_cast<int64_t*>(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<typename T>
T ProfilerCall::StringTable<T>::getId(const std::string &str) {
auto res = stringLookupTable.find(str);
T index;
if (res == stringLookupTable.end()) {
index = static_cast<T>(strings.size());
strings.push_back(str);
stringLookupTable[str] = index;
} else {
index = res->second;
}
return index;
}
template<typename T>
std::string ProfilerCall::StringTable<T>::getString(T id) {
return strings[static_cast<typename decltype(stringLookupTable)::size_type>(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<MetricBackend*> &metricBackends,
const MmapAllocator<char> &alloc)
: frameQueue(MmapAllocator<ProfilerCall>(alloc)),
callQueue(MmapAllocator<ProfilerCall>(alloc)),
drawcallQueue(MmapAllocator<ProfilerCall>(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<const ProfilerCall::data*>(queryData));
break;
case QUERY_BOUNDARY_DRAWCALL:
drawcallQueue.emplace_back(eventId,
reinterpret_cast<const ProfilerCall::data*>(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<MetricBackend*>* ProfilerQuery::metricBackends = nullptr;
ProfilerCall::StringTable<int16_t> ProfilerCall::nameTable;