我正在设置一个记录器类,并希望优化记录。 它必须是多色记录仪,因此std :: string :: append(...)不是一个选择。
将新日志添加到字符串向量不是一个好主意,因为每个push_back内存都会增加,而fps则会下降。我想创建一个Log
结构,该结构将容纳string msg
和color
或flag
并告知我们该消息是哪种消息,并创建一个双缓冲区Log
结构。写入第一个对象,然后将其传递给第二个Log
对象并从中进行绘制,然后清除第一个Log
对象...依此类推。我尝试实现它,但是它并没有按我希望的那样工作。
此刻我离开了Logs向量
class Logger
{
public:
struct Log {
std::string text;
Uint color;
}
void Draw() {
for(const auto& log : logs) {
renderer->DrawString(log.text, log.color);
}
}
void AddLog(const std::string& text, Uint color) {
logs.emplace_back(text, color);
}
std::vector<Log> logs;
};
int main() {
//window stuff, opengl context, etc.
Logger logger;
while(!quit) {
// Do not flood logger with logs, just add it sometimes
static double lastTime = -1.0;
if(time - lastTime >= 0.20f) {
logger.AddLog("Log", 0xff00ffff);
lastTime = time;
}
logger.Draw();
}
return 0;
}
我们不会将位置传递到renderere->DrawString(...)
,因为它会自动向下移动到另一行。
这种方法有效,但是速度非常非常非常非常慢。
我如何优化它?我想得到类似CS go console的东西。它也是一种多色记录器,它可以记录大量消息而不会导致fps下降。
答案 0 :(得分:2)
为了避免在将日志消息推送到记录器时重新分配向量,可以使用环形缓冲区结构。它为N条消息预分配内存,并且仅存储最新推送的N条消息。一个简单的实现可以如下:
template <std::size_t bufferSize>
class Logger {
public:
struct Data {
std::string msg = " - ";
uint32_t color = 0x00000000;
};
void addLog(Data && item) {
buffer_[head_] = std::move(item);
if (++head_ >= bufferSize) head_ -= bufferSize;
}
void draw() const {
for (std::size_t i = 0; i < bufferSize; ++i) {
auto idx = head_ + i;
if (idx >= bufferSize) idx -= bufferSize;
// print the log whatever way you like, for example:
printf("%s\n", buffer_[idx].msg.c_str());
}
}
private:
std::size_t head_ = 0;
std::array<Data, bufferSize> buffer_;
};
此处,模板参数bufferSize
指定环形缓冲区的大小。 draw()
方法首先处理最早的消息,因此最新的日志将位于底部。
这是一个实时示例:link