Сижу вот изучаю Rust
Как вы, наверное, знаете, в C/C++ есть
И компилятор там всеми силами пытается его соптимайзить, фигачит
В Rust есть по сути тоже самое, но еще и со строками (
Короче - сам поиск примерно никак, используется линейный поиск, но оптимизируется сравнение строк.
Единственное, если размер строк разный, то он сделает jump table по их размеру (по сути, как с обычными числами)
А вот со сравнением строк уже интереснее. Да да, это скорее всего уже не сам раст, сколько llvm, но все равно интересно
1) Если строки <8 байт, то строка запишется как число, и компилятор просто прочитает строку как число и сделает сравнение
2) Если строки <16 байт, то сделает два сравнения (два числа 8 байт)
3) Если строки <32(?) байта, то фиганет SIMD сравнение (строки все еще числа)
4) Иначе, вызовет какую-то функцию сравнения длинных строк, которая, думаю, использует какие-то идеи из 1-3
Обидно конечно, что он не оптимайзит для длинных строк ничего. В моем случае (см картинку) очевидно, что можно понять, какая именно строка нужна по первому символу даже, и дальше сделать всего-лишь 1 проверку.
May be one day я решусь залезть в llvm...
Так что если вдруг кто-то решит переписать ejudge на раст, то придется и для него кодогенерировать бор для команд...
Как вы, наверное, знаете, в C/C++ есть
switch
, который работает для чиселИ компилятор там всеми силами пытается его соптимайзить, фигачит
jump table
какой-то или около тогоВ Rust есть по сути тоже самое, но еще и со строками (
match str
), и возник вопрос, а как оно там, собственно, оптимизируетсяКороче - сам поиск примерно никак, используется линейный поиск, но оптимизируется сравнение строк.
Единственное, если размер строк разный, то он сделает jump table по их размеру (по сути, как с обычными числами)
А вот со сравнением строк уже интереснее. Да да, это скорее всего уже не сам раст, сколько llvm, но все равно интересно
1) Если строки <8 байт, то строка запишется как число, и компилятор просто прочитает строку как число и сделает сравнение
2) Если строки <16 байт, то сделает два сравнения (два числа 8 байт)
3) Если строки <32(?) байта, то фиганет SIMD сравнение (строки все еще числа)
4) Иначе, вызовет какую-то функцию сравнения длинных строк, которая, думаю, использует какие-то идеи из 1-3
Обидно конечно, что он не оптимайзит для длинных строк ничего. В моем случае (см картинку) очевидно, что можно понять, какая именно строка нужна по первому символу даже, и дальше сделать всего-лишь 1 проверку.
May be one day я решусь залезть в llvm...
Так что если вдруг кто-то решит переписать ejudge на раст, то придется и для него кодогенерировать бор для команд...
godbolt.org
Compiler Explorer - Rust (rustc 1.55.0)
// Type your code here, or load an example.
pub fn some(s: &str) -> i32 {
match s {
"asomessmesomdsomesomesomesomessmesomdsomesomesome" => 0,
"bothrothrothrothrothrothrothrothrothrothrothrothr" => 1,
"cstufstufstufstufstufstuf…
pub fn some(s: &str) -> i32 {
match s {
"asomessmesomdsomesomesomesomessmesomdsomesomesome" => 0,
"bothrothrothrothrothrothrothrothrothrothrothrothr" => 1,
"cstufstufstufstufstufstuf…
👍1
В Go можно написать простой rate-limiter, который ограничивает нагрузку, двумя способами: перед запуском горутины, или внутри нее. Я вот не задумывался, что они отличаются довольно сильно в плане порядка обработки запросов
За подробностями прошу сюда: https://leviska.notion.site/3dbe7633fd5449ff99c485d147f2d420
За подробностями прошу сюда: https://leviska.notion.site/3dbe7633fd5449ff99c485d147f2d420
Лев's Notion on Notion
Рейтлимитер: внутри или снаружи | Notion
Начнем с простого: зачем нужен рейтлимитер?
👍1
Написал что-то похожее на kwargs, но статически типизированное и на расте. Не спрашивайте меня зачем. playground
Немного макросов, и я думаю, что можно сделать даже красиво
https://twitter.com/leviska0/status/1536502738237931520
Немного макросов, и я думаю, что можно сделать даже красиво
https://twitter.com/leviska0/status/1536502738237931520
👍3
Я все долго хотел написать пост про раст, и, наверное, когда-то его напишу, но недавно нашел это прекрасное видео, которое рассказывает про тот самый safety, что дает Rust, сравнивая куски кода с C++. Если вы все задавались вопросом "да кто такая безопасность в этом вашем расте", то видео очень хорошее
https://www.youtube.com/watch?v=IPmRDS0OSxM
https://www.youtube.com/watch?v=IPmRDS0OSxM
YouTube
A Firehose of Rust, for busy people who know some C++
Slides: https://jacko.io/firehose_of_rust
The slower version of this talk (2h32m): https://youtu.be/FSyfZVuD32Y
Contents:
0:00:00 introduction
0:04:03 references and mutable aliasing
0:06:54 reference lifetime examples
0:22:12 mutable aliasing examples
0:50:16…
The slower version of this talk (2h32m): https://youtu.be/FSyfZVuD32Y
Contents:
0:00:00 introduction
0:04:03 references and mutable aliasing
0:06:54 reference lifetime examples
0:22:12 mutable aliasing examples
0:50:16…
Где-то год назад я полностью осознал казалось бы очень простую мысль: "все программирование, все, с чем мы работаем, это все код. Код, который зачастую опенсорсный, куда ты можешь зайти, почитать его, и если вдруг нужно - поменять"
"Well, duh", скажете вы, но главная суть этой идеи в том, что менять опенсорсный код - это нормально и не так уж и сложно. Например, если вы выбираете какую-то библиотеку или инструмент для работы, и он вот чуть чуть не делает того, что вам надо, то у вас есть возможность просто сесть и доделать это. Не надо ныть, что "уу хорошая библиотека, но вот фичу не умеет", не надо искать другие менее популярные (и более багованые) аналоги, просто сядь и пофикси (лол)
Вчера вот я вышел на новый уровень какой-то: в Go есть хорошая ORM библиотека для БД gorm, и есть хороший инструмент для миграций goose, написанный на го, и в котором можно в том числе писать миграции на го. Но вторая штука не умеет работать из коробки с
Я пошел в репу и нашел PR, который за 10 строчек добавляет возможность удобно подрубить
Три часа дебаггинга спустя, я нашел забытый
Но почему я решил этим поделиться: для меня лично это был новый уровень, когда я фиксил даже не саму либу, а чей то пр этой либы. Т.е. мало того, что я решил не искать аналог и пофиксить уже хороший инструмент, так я не стал в очередной раз городить велосипед, а нашел уже чей-то другой велосипед и починил пару костылей в нем.
Вторая причина, почему я хотел этим поделиться, это попытаться завлечь вас делать так же. Я часто обсуждаю всякую прогу с друзьями и коллегами, и часто слышу как люди сталкиваются с похожими проблемами "вот есть штука, но она делает почти все, что надо", на что я отвечаю "ну просто пофикси лол))", и люди думают, что я шучу, мол "да зачем", "ой лезть еще туда", "я не смогу" и т.д., но при этом ни разу не пробовали так делать. За последние два года у меня уже накопилось несколько контрибьюшенов в опенсорс софт, и все эти контрибьюшены (не считая опенсорсных репозиториев с работы) были ровно такими же: есть хороший инструмент, но нужна какая-то мелочь, сел, разобрался, добавил эту мелочь, получил свои фичи и плюс в карму за помощь в разработке опенсорса. И скажу честно: в первые разы было очень тяжело, я действительно тратил много времени (несколько дней), чтобы просто разобраться в чужом коде, но это просто скилл, причем очень полезный, и я крайне рекомендую в следующий раз, когда от хорошего инструмента будет нужна еще какая-то мелочь, просто сесть и добавить ее
"Well, duh", скажете вы, но главная суть этой идеи в том, что менять опенсорсный код - это нормально и не так уж и сложно. Например, если вы выбираете какую-то библиотеку или инструмент для работы, и он вот чуть чуть не делает того, что вам надо, то у вас есть возможность просто сесть и доделать это. Не надо ныть, что "уу хорошая библиотека, но вот фичу не умеет", не надо искать другие менее популярные (и более багованые) аналоги, просто сядь и пофикси (лол)
Вчера вот я вышел на новый уровень какой-то: в Go есть хорошая ORM библиотека для БД gorm, и есть хороший инструмент для миграций goose, написанный на го, и в котором можно в том числе писать миграции на го. Но вторая штука не умеет работать из коробки с
gorm
, и в итоге по сути надо делать два соединения с бд и работать с gorm
через глобальную переменную, что не является проблемой, но блин некрасиво!Я пошел в репу и нашел PR, который за 10 строчек добавляет возможность удобно подрубить
gorm
. Но чел этот пр видимо не запускал, и когда я запустил его у себя локально, то у меня все ушло в вечный цикл и ничего не работало.Три часа дебаггинга спустя, я нашел забытый
return nil
, форкнул форк, пофиксил в нем багу, и теперь все хорошо работаетНо почему я решил этим поделиться: для меня лично это был новый уровень, когда я фиксил даже не саму либу, а чей то пр этой либы. Т.е. мало того, что я решил не искать аналог и пофиксить уже хороший инструмент, так я не стал в очередной раз городить велосипед, а нашел уже чей-то другой велосипед и починил пару костылей в нем.
Вторая причина, почему я хотел этим поделиться, это попытаться завлечь вас делать так же. Я часто обсуждаю всякую прогу с друзьями и коллегами, и часто слышу как люди сталкиваются с похожими проблемами "вот есть штука, но она делает почти все, что надо", на что я отвечаю "ну просто пофикси лол))", и люди думают, что я шучу, мол "да зачем", "ой лезть еще туда", "я не смогу" и т.д., но при этом ни разу не пробовали так делать. За последние два года у меня уже накопилось несколько контрибьюшенов в опенсорс софт, и все эти контрибьюшены (не считая опенсорсных репозиториев с работы) были ровно такими же: есть хороший инструмент, но нужна какая-то мелочь, сел, разобрался, добавил эту мелочь, получил свои фичи и плюс в карму за помощь в разработке опенсорса. И скажу честно: в первые разы было очень тяжело, я действительно тратил много времени (несколько дней), чтобы просто разобраться в чужом коде, но это просто скилл, причем очень полезный, и я крайне рекомендую в следующий раз, когда от хорошего инструмента будет нужна еще какая-то мелочь, просто сесть и добавить ее
👍7
Как выражать логику через систему типов, или пишем код, который не дает багать
https://leviska.notion.site/33f6445acb704440b57faae727123572
Я долго хотел написать этот пост, но все не мог найти хороший пример и не скатиться в "объяснение что такое Rust и почему он крута" на 30 страниц. И вроде бы получилось.
Если вы программируете на C++ и не понимаете вот этого хайпа вокруг Rust насчет "компилируется - значит работает" - пост для вас, с примерами на C++ и сравнением двух реализаций
https://leviska.notion.site/33f6445acb704440b57faae727123572
Я долго хотел написать этот пост, но все не мог найти хороший пример и не скатиться в "объяснение что такое Rust и почему он крута" на 30 страниц. И вроде бы получилось.
Если вы программируете на C++ и не понимаете вот этого хайпа вокруг Rust насчет "компилируется - значит работает" - пост для вас, с примерами на C++ и сравнением двух реализаций
Лев's Notion on Notion
Как выражать логику через систему типов | Notion
Или пишем код, который не дает багать
👍7
Еще когда я даже не учил Rust, но спрашивал у знающих знакомых "как работает XXX", меня часто не удовлетворял ответ: казалось, что для того, чтобы писать такой же эффективный код на
Возьмем
Плюсы говорят "вот тип, вы можете проверять, лежит ли в нем что-то, а можете не проверять, так как уже проверяли когда-то до этого, нам пофиг. Но если не проверите, то будет бобо"
Раст говорит "вот тип, вы или должны проверить, или должны явно указать, что вы умнее через
И во времена, когда я был ярым C++сером, мне казалось, что это будет как в плюсах, только неудобнее, потому что я даже не подозревал, что можно лучше.
Простой пример, как в C++ проверить, что что-то лежит внутри
Ногоспади спасибо разрабам раста конечно же никто так не пишет. Вместо этого, в Rust вы пытаетесь показать свою идею через систему типов. В данном случае вы хотите показать, что "вот тут я проверил
Но помимо этого, как я говорил, мы переложили ответственность следить за типами на компилятор. Поэтому, например, если кто-то удалит строчки с
Лично я называю это "писать код в стиле Rust". С одной стороны - по сути это просто синтаксический сахар, реальной разницы после компиляции (вроде бы) нет. Но с другой стороны, последний вариант читаемее и безопаснее. Иногда у меня возникает ощущение, что некоторые люди очень поверхностно изучают Rust и пытаются писать "как на плюсах", расстраиваются, и возвращаются обратно. Но если бы они приложили больше усилий, то вполне возможно, их мнение было бы совсем другим.
Rust
, как и на C++
, мне бы пришлось постоянно использовать unsafe
.Возьмем
Option/optional
:Плюсы говорят "вот тип, вы можете проверять, лежит ли в нем что-то, а можете не проверять, так как уже проверяли когда-то до этого, нам пофиг. Но если не проверите, то будет бобо"
Раст говорит "вот тип, вы или должны проверить, или должны явно указать, что вы умнее через
unsafe
"И во времена, когда я был ярым C++сером, мне казалось, что это будет как в плюсах, только неудобнее, потому что я даже не подозревал, что можно лучше.
Простой пример, как в C++ проверить, что что-то лежит внутри
optional
и получить значение:if (optional_value != nullopt) {Если это в лоб переписать на Rust, получим:
auto value = *optional_value; // используем "небезопасную" штуку без проверки, но мы же молодцы, мы проверили
std::cout << value << std::endl;
}
if optional_value.is_some() {И когда я получал ответ на свой вопрос, мне казалось что как-то так оно и работает и люди реально пишут такой код
let value = unsafe { optional_value.unwrap_unchecked() };
println!("{}", value);
}
Но
Option
, и 100% у меня лежит там значение" <=> вы бы хотели вместо Option<T>
иметь тип T
. И вместо того, чтобы держать это все в голове/комментариях (как в случае C++), мы выражаем это в типах, и перекладываем ответственность следить за типами на компилятор:if let Some(value) = optional_value {В первую очередь мне нравится то, что это тупо короче и читаемее (имхо). Мы буквально написали "если в
// typeof(value) == T
println!("{}", value);
}
Option
лежит что-то, то дай значение, иначе пропусти ветку" в одну строчку.Но помимо этого, как я говорил, мы переложили ответственность следить за типами на компилятор. Поэтому, например, если кто-то удалит строчки с
if
(или переместит/скопирует тело if
), то первые два варианта нормально скомпилируются, но последний - нет (т.к. у вас просто нет переменной value
)Лично я называю это "писать код в стиле Rust". С одной стороны - по сути это просто синтаксический сахар, реальной разницы после компиляции (вроде бы) нет. Но с другой стороны, последний вариант читаемее и безопаснее. Иногда у меня возникает ощущение, что некоторые люди очень поверхностно изучают Rust и пытаются писать "как на плюсах", расстраиваются, и возвращаются обратно. Но если бы они приложили больше усилий, то вполне возможно, их мнение было бы совсем другим.
👍6😁1🤔1