Как стать автором
Обновить
2
0
Александр @aegoroff

.NET, Go, Rust

Отправить сообщение

И в чем сокращение? Ноль на букву k заменили? Это больше на запутывание похоже

Мне vscode + rust analyzer больше понравилась. Rust Rover уступает им, как мне кажется

Мы пробовали, точнее использовали - оцелот был в продукте пару (или немного больше) лет. В общем - там куча багов, приходится все обставлять костылями, про более менее серьезную нагрузку вообще молчу, в итоге - заменили на Traefik, убрали кучу костылей, получили достаточную нам производительность, отсутствие глюков, и в итоге конфигурация оказалось даже проще, ну и бонусом - наличие документации, коей не может быть на самопале, сделанном с использованием оцелота. Выбирать вам.

не очень понял фразу "Горутина состоит из 70 в коде" - 70 чего? полей? байт? чего-то еще?

автор вроде написал в конце "В Rust я пробовал менять sqlx на tokio-postgres, убирал расшифровку JWT, результат тот же.", говорит не помогло

У меня 6 на 256 - обновил и никаких проблем

можете глянуть мои наработки https://github.com/aegoroff/bstore - образ весит 20 мегабайт, но там внутри SQLite есть и много чего еще

Hello world можно сделать еще меньше - добавьте эти строчки в Cargo.toml

[profile.release]
strip = true
lto = true
panic = 'abort'

Для безопасности попробуйте еще https://console.cloud.google.com/gcr/images/distroless/GLOBAL/static-debian12:latest/details?pli=1
Но вы должны быть готовы что не сможете никак отлаживать контейнер, т.к. там вообще ничего нет, ни шелла ни даже glibc

Не смотрел твой код. В комменте только написал "не удивлюсь если".

я посмотрел - я бы не стал пользоваться ORM, которая даже теоретически (пусть там супер пупер экранирование) допускает попадание внешних данных в тело запроса

    fn add<T>(&self, data: T) -> QueryBuilder<T, T, ORM>
        where T: for<'a> Deserialize<'a> + TableDeserialize + TableSerialize + Serialize + Debug + 'static
    {
        let table_name = data.name();
        let types = serializer_types::to_string(&data).unwrap();
        let values = serializer_values::to_string(&data).unwrap();
        let query: String = format!("insert into {table_name} {types} values {values}");
        let qb = QueryBuilder::<T,T, ORM> {
            query: query,
            entity: Default::default(),
            orm: self,
            result: std::marker::PhantomData,
        };
        qb
    }

ну его в качель, уж лучше самому, используя тот же sqlx или дизель, работать, чем с подобным.

  • protect() - экранирует строку от SQL-инъекций


Зачем это нужно? Нет, я понимаю что такое SQL инъекция и что плохо когда неконтролируемые внешние данные могут попадать в код строящий запросы к базе, я о другом - ЗАЧЕМ вообще разрешать такому коду попадать в запросы? Уже 100 лет в обед, во ВСЕХ СУБД имеется механизм параметризованных запросов, если нужно внешние данные использовать при, например фильтрации, сортировке и т.д. Вероятность неправильно сделать экранирование (накосячить, не знать и т.д.) весьма высока причем даже самим создателям БД, которые знают синтаксис досконально, а цена такой ошибки просто может быть фатальной.

В общем, мой посыл - что подставлять внешние данные в тело запроса, должно быть ЗАПРЕЩЕНО, на уровне код стайла и никаких тут не может быть исключений.

Поддерживаю - постоянное добавление новых возможностей потихоньку превращает его в C++ в котором можно сделать одно и тоже отстрелить себе ногу 1001 способом. Как мне кажется, на версии 8 вполне можно было остановиться - выразительности более чем достаточно, а дальнейшее добавление новых фич будет лишь во вред

В теории все верно, но работают реальные люди со своими слабостями, - безопасность работает только тогда, когда она удобна и незаметна, а все эти ДОЛЖНО, НАДО - не работают. Можно объяснить (и контролировать) одному, десяти, ну пусть 100 людям, но если их тысячи - обязательно найдется слабое звено и все насмарку - одна дырка, и вся выстроенная, дорогостоящая оборона рухнет

ну да, это по сути микробенчмаркинг и от такого вреда (за пропаганду плохого стиля) больше чем пользы, такое сработает разве что в действительно нагруженном игровом движке или например в коде брутфорса тех же паролей и то после того как профайлер покажет узкое место.

вопрос только - зачем? Оптимизация IO кода это скорее минимизация запросов к медленным источникам, например используя тот же фильтр Блума, но это совсем не то, о чем говорится в статье.

Вот что хочется сказать автору статьи

  1. Грубо, весь код можно поделить на 2 класса - CPU bound и IO bound - второго кода, в реальной системе, подавляющее большинство, т.е. по факту, процессор в современном приложении большую часть времени ждет (сеть, диск итд). IO bound коду будет параллельно насколько циклов процессора будет быстрее считаться маленький кусочек кода, но подобная лапша окажет ОЧЕНЬ существенное влияние на производительность программиста.

  2. Первое правило оптимизации - сначала профайлер! И именно не профилирование конкретного изолированного кусочка кода, а приложения в целом.

  3. Всегда работает правило паретто (80/20), а в таких вещих, коэффициенты еще более экстремальны, вплоть до 100/1 - те только 1% кода СУЩЕСТВЕННО влияет на производительность

  4. И вот только тогда, когда профайлер покажет что именно вот этот CPU bound код вызывает реальные проблемы с производительность - только тогда стоит применять фокусы описанные в этой статье.

  5. Идем далее - даже в CPU bound коде, очень существенное влияние на производительность оказывают аллокации памяти и в первую очередь смотреть стоит в эту сторону

Вот например https://kb.comindware.ru/article/Расширения-comindware-Примеры-использования-1481.html но вообще там собственно вся база на тройках и сделана (по крайней мере до внедрения апач игнайт). Все что вы вносите в базу, в виде этих троек (фактов) там и хранится.

Есть

let mut stmt = self.conn.prepare("SELECT id, title, created, short_text, markdown \
                    FROM post INNER JOIN post_tag ON post_tag.post_id = post.id 
                    WHERE is_public = 1 AND post_tag.tag = ?3 ORDER BY created DESC LIMIT ?1 OFFSET ?2")?;
let files = stmt.query_map(
    [limit.to_string(), offset.to_string(), tag],
    Sqlite::map_small_post_row,
)?;
files.filter_map(std::result::Result::ok).collect()

угу, особенно что там написано что for более идеоматичен в широком смысле а for_each просто более удобен в случае длинных цепочек и иногда просто быстрее работает:

"This is equivalent to using a for loop on the iterator, although break and continue are not possible from a closure. It’s generally more idiomatic to use a for loop, but for_each may be more legible when processing items at the end of longer iterator chains. In some cases for_each may also be faster than a loop, because it will use internal iteration on adapters like Chain."

А если у вас ваш аудиоплеер собран с выводом через пульсу, а не alsa, то что будет?

а вот не знаю - я такое сам не делал, только заменял пульсу на пайпвайр - вроде все работает нормально

А чем генту собирать сложно? emerge и собрал.

Сложно :) без специальных знаний. Это как за руль болида формулы один посадить обычного, пусть даже опытного водителя - он даже с места не сможет стронуться, не говоря уже про то, чтобы ехать.

Мне не нужен bluetooth, wifi и pulseaudio, как выпилить в арче?

а разве pacman -R pulseaudio и т.д. не работает?

А вот z3 в llvm/clang был бы полезен, тогда как в арче, судя по pkgbuild'ам, они собираются без z3. Как запилить в арче?

ну если очень надо можно свой pkgbuild (и соотв. сделать свой aur) запилить на основе существующего - это проще чем генту собирать

На ryzen 9 7950 можно не ждать!

да, но речь идет о виртуалке в облаке + не у всех такая железка есть + при выходе новых версий нужно постоянно все пересобирать - сомнительное удовольствие

1
23 ...

Информация

В рейтинге
Не участвует
Откуда
Москва, Москва и Московская обл., Россия
Дата рождения
Зарегистрирован
Активность