如何创建优化的图形多色记录仪?

时间:2018-12-23 11:05:50

标签: c++ user-interface logging graphics

我正在设置一个记录器类,并希望优化记录。 它必须是多色记录仪,因此std :: string :: append(...)不是一个选择。

将新日志添加到字符串向量不是一个好主意,因为每个push_back内存都会增加,而fps则会下降。我想创建一个Log结构,该结构将容纳string msgcolorflag并告知我们该消息是哪种消息,并创建一个双缓冲区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下降。

1 个答案:

答案 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