Как я могу создать оптимизированный графический многоцветный регистратор? - PullRequest
0 голосов
/ 23 декабря 2018

Я настраиваю класс логгера и хочу оптимизировать логирование.Это должен быть многоцветный логгер, поэтому 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.Это также многоцветный регистратор, который может записывать массивные сообщения без потери fps.

1 Ответ

0 голосов
/ 23 декабря 2018

Чтобы избежать перераспределения вашего вектора при отправке сообщений журнала на ваш регистратор, вы можете использовать структуру кольцевого буфера.Он предварительно выделяет память для сообщения 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() сначала обрабатывает самые старые сообщения, поэтому ваши новейшие журналы будут внизу.

Вот живой пример: ссылка

...