Re[3]: быстрый sprintf
От: McQwerty Россия  
Дата: 03.11.22 10:12
Оценка: +1
Здравствуйте, maks1180, Вы писали:

M>>>1) передача размера буффера отпадает, так как придеться постоянно проверять не вышли ли мы за границы буфера, что существенно снизит скорость.

MQ>>Без профилировки такое утверждать весьма тяжело.
M>Почему ? Дополнительная проверка всегда приводит к снижению скорости. Разве это не очевидно ?

Чтобы сказать "существенно" — нужно смотреть удельный вес этих проверок ко всем остальным действиям.
Re: быстрый sprintf
От: sergii.p  
Дата: 03.11.22 11:50
Оценка:
Здравствуйте, maks1180, Вы писали:

M>Нужно реализовать быстрый sprintf, соотвественно:


проблема sprintf, что он создаёт строку как промежуточное звено между источником и получателем.
Можно попробовать сделать ленивую строку, которая будет хранить необходимую информацию для форматирования и только при итерировании по ней будет проводить необходимые вычисления. Примерный draft:

#include <variant>
#include <optional>

// методы begin и end надо реализовать и реализацию Iter в зависимости от функции next()
struct CharIterable {
    struct Iter{};
    std::optional<Iter> next( return std::nullopt; ) const;
};

struct IntValue: CharIterable
{
    private: int val = 0;
};

struct StrValue: CharIterable
{
    private: const char* val = "";
};

using Value = std::variant<IntValue, StrValue>;

template<int N>
struct LazyFormatter: CharIterable
{
    private: const char* format;
    private: Value values[N];
};

template<>
struct LazyFormatter<0>: CharIterable
{
    public: LazyFormatter(const char* fromat){};
    private: const char* format;
};

template<int N>
auto operator+(const LazyFormatter<N>& f, Value v) {
    return LazyFormatter<N + 1>{};
}

int main() {
    const auto to_log = LazyFormatter<0>{"{}{}"} + IntValue{} + StrValue{};
    return 0;
}


new/delete нет. Всё на стеке. Я не уверен, что овчинка стоит выделки. Надо мерять. Но оно точно понадёжнее, чем играться с регистрами.

Намного проще решение — предположить что int при форматировании никогда не превысит размера 11 н-р. double — 15 и т д. И делать конкатенацию сразу

stack_string{"int value: "} + stack_string::fromInt(42) + stack_string{ ", some string value: " } + stack_string::fromStaticStr("text");


тоже динамической аллокации нет. Но тут мы имеем некоторый перерасход за счёт наших допущений на максимальную длину. Ну и не constexpr строку не засунуть
Re: быстрый sprintf
От: maks1180  
Дата: 08.11.22 19:15
Оценка:
M>Второй вариант:
M>1) выделяем память в стеке по мере парсинга шаблона.
M>Насколько я понимаю несколько вызовов alloca дадут единый кусок памяти общим объёмом не меньше чем сумма вызовов alloca. Это так ?

Начал делать и наткнулся на глупую ошибку в проектировании: несколько вызовов alloca дают единый кусок памяти — это действительно так, только стек уменьшается, адрес второго блока будет меньше чем первого. Поэтому можно конечно задом наперёд строку формировать или с конца парсить, только при этом насколько я понимаю скорость при копирования будет ниже.
Либо кусками память выделять и ссылаться один кусок на другой будет.
===============================================
(реклама, удалена модератором)
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.