причины почему именно #rust ?
так же минимальное сравнение #rust с #python, #golang
https://www.youtube.com/watch?v=DnT-LUQgc7s
так же минимальное сравнение #rust с #python, #golang
https://www.youtube.com/watch?v=DnT-LUQgc7s
YouTube
Considering Rust
The Rust programming language has become a serious contender in the space of "systems" programming languages, and has recently been adopted by many of the tech giants for "serious" projects. In response to this, more companies are now considering whether…
Forwarded from Блог*
#prog #rust #моё
В Rust в некоторых случаях можно использовать анонимный лайфтайм (
Времена жизни — пожалуй, именно та фича, которая больше всего делает Rust непохожим на мейнстримные языки программирования. В частности, их синтаксис (
Раскрытие сокращённой записи начинается с введения нового явного параметра для каждого аргумента, тип которого параметризован временем жизни (далее ВЖ), но для которого конкретное значение ВЖ не указано. Например, если у нас функция
Далее компилятор пытается приписать времена жизни возвращаемому типу. В обычном коде произвольные времена жизни не материализуются из ничего, они появляются из ссылок на имеющиеся значения. Логично предположить, что если у тебя есть функция с ВЖ, то ВЖ возвращаемого типа должно быть связано с аргументами. Если аргументов нет вовсе, то компилятор откажется компилировать функцию. Если аргумент есть только один и с одним обобщенным параметром ВЖ, то возвращаемый тип параметризуется этим ВЖ для всех возможных обобщённых параметров. Например, если есть функция
В Rust в некоторых случаях можно использовать анонимный лайфтайм (
'_). Практика показывает, что эта фича некоторым не до конца понятна, поэтому я решил написать об этом подробнее.Времена жизни — пожалуй, именно та фича, которая больше всего делает Rust непохожим на мейнстримные языки программирования. В частности, их синтаксис (
'identifier) — это то, что приходит первым на ум тому, кто уверяет, что у Rust нечитаемый синтаксис. Тем не менее, если взглянуть на код программы на Rust, то этих времён жизни можно увидеть очень мало. Казалось бы, как так может быть, если учесть, что каждая ссылка параметризована временем жизни, а ссылки в Rust используются достаточно активно? Дело в том, что бо́льшая часть вариантов использования времён жизни подпадает под один из достаточно простых паттернов, для которых компилятор в состоянии вывести отсутствующие времена жизни сам. Это называется lifetime elision, и правила, по которым оно происходит, перечислены в растономиконе. Раскрытие сокращённой записи начинается с введения нового явного параметра для каждого аргумента, тип которого параметризован временем жизни (далее ВЖ), но для которого конкретное значение ВЖ не указано. Например, если у нас функция
fn do_something(a: &mut u32, b: (&u32, &u32), c: Cow<str>) { ... }
, то после первого шага преобразования она выглядит так:fn do_something<'lt1, 'lt2, 'lt3, 'lt4>(a: &'lt1 mut u32, b: (&'lt2 u32, &'lt3 u32), c: Cow<'lt4, str>) { ... }
Обратите внимание, это работает не только с ссылками.Далее компилятор пытается приписать времена жизни возвращаемому типу. В обычном коде произвольные времена жизни не материализуются из ничего, они появляются из ссылок на имеющиеся значения. Логично предположить, что если у тебя есть функция с ВЖ, то ВЖ возвращаемого типа должно быть связано с аргументами. Если аргументов нет вовсе, то компилятор откажется компилировать функцию. Если аргумент есть только один и с одним обобщенным параметром ВЖ, то возвращаемый тип параметризуется этим ВЖ для всех возможных обобщённых параметров. Например, если есть функция
fn first_and_second(arg: &(u32, u32, u32))- > (&u32, &u32) {
(&arg.0, &arg.1)
}
, то её развёрнутый тип будетfn first_and_second<'a>(arg: &'a (u32, u32, u32))- > (&'a u32, &'a u32) {
(&arg.0, &arg.1)
}
Что же делать, если аргументов несколько? В случае, когда функция принимает &self или &mut self, ВЖ возвращаемого типа приравнивается ВЖ self. Из этого, кстати, следует несколько неожиданный результат, что нижеприведённый код не компилируется:struct Foo;Если расписать тип полностью, то станет понятно, почему:
impl Foo {
fn use_str(&self, s: &str) -> &str {
s
}
}
struct Foo;Действительно, lifetime elision приводит к тому, что возвращаемая строка имеет то же ВЖ, что и
impl Foo {
fn use_str<'foo, 's>(&'foo self, s: &'s str) -> &'foo str {
s
}
}
self, но в теле функции используется строка с другим ВЖ 's, которое никак не связано с 'foo. Для того, чтобы решить эту проблему, нужно явно ввести обобщённый параметр времени жизни и указать, что он один и тот же у аргумента и возвращаемого значения:struct Foo;Такой код уже компилируется.
impl Foo {
fn use_str<'s>(&self, s: &'s str) -> &'s str {
s
}
}
Telegram
folex in codingteam
Не выходит прототипировать на расте у меня
модель атомик памяти в #CPP (полностью такая же для #rust)
- Неделимый, но расслабленный (relaxed)
- Полный порядок (seq_cst)
- Синхронизация пары (Acquire/Release)
https://habr.com/ru/post/517918/
- Неделимый, но расслабленный (relaxed)
- Полный порядок (seq_cst)
- Синхронизация пары (Acquire/Release)
https://habr.com/ru/post/517918/
Хабр
std::atomic. Модель памяти C++ в примерах
Для написания эффективных и корректных многопоточных приложений очень важно знать какие существуют механизмы синхронизации памяти между потоками исполнения, какие гарантии предоставляют элементы...
Крутющая статья о енамах в #rust есть и места сравнения с #C
= Peeking inside a Rust enum
https://fasterthanli.me/articles/peeking-inside-a-rust-enum
= Peeking inside a Rust enum
https://fasterthanli.me/articles/peeking-inside-a-rust-enum
fasterthanli.me
Peeking inside a Rust enum
During a recent Rust Q&A Session on my twitch channel, someone asked a question that seemed simple: why are small string types, like SmartString or SmolStr, the same size as String, but small vec t...
блинский. только сейчас заметил что мне выдает компилятор при попытке скомпилировать асинхронный трэйт в #rust... и этот пакет прямо рекламируется! и действительно весь геморой с ними решаются макросами и афигенно рботает !
https://crates.io/crates/async-trait
рубрика "надо чаще обновлять компилятор раста" много нового можно черпануть)))
https://crates.io/crates/async-trait
рубрика "надо чаще обновлять компилятор раста" много нового можно черпануть)))
Unterstanding Rust’s Vec and its capacity for fast and efficient programs
https://markusjais.com/unterstanding-rusts-vec-and-its-capacity-for-fast-and-efficient-programs/
про выделение памяти для вектора в #rust
https://markusjais.com/unterstanding-rusts-vec-and-its-capacity-for-fast-and-efficient-programs/
про выделение памяти для вектора в #rust
Forwarded from Блог*
#prog #rust
Пара слов о трейте Copy.
Во-первых, это один из "магических" трейтов, помечен атрибутом
В-третьих, как сказано в документации к
Продемонстрирую на примере:
Пара слов о трейте Copy.
Во-первых, это один из "магических" трейтов, помечен атрибутом
#[lang = "copy"]. Компилятор проверяет, что если тип тем или иным способом задекларирован как Copy, то и всего его поля должны быть Copy. Следующий код не компилируется:#[derive(Clone, Copy)]Ошибка:
struct StringHolder(String);
error[E0204]: the trait `Copy` may not be implemented for this type
--> src/lib.rs:1:17
|
1 | #[derive(Clone, Copy)]
| ^^^^
2 | struct StringHolder(String);
| ------ this field does not implement `Copy`
Во-вторых, один и тот же тип не может реализовывать Copy и Drop одновременно. Скажем, следующий код не компилируется:#[derive(Clone, Copy)]Ошибка:
struct Primitive;
impl Drop for Primitive {
fn drop(&mut self) {}
}
error[E0184]: the trait `Copy` may not be implemented for this type; the type has a destructorТак как полноценных negative trait bounds в Rust всё ещё нет, ограничение
--> src/lib.rs:1:17
|
1 | #[derive(Clone, Copy)]
| ^^^^ Copy not allowed on types with destructors
Copy можно использовать как более сильную замену ограничению !Drop.В-третьих, как сказано в документации к
Copy, "Copies happen implicitly, for example as part of an assignment y = x. The behavior of Copy is not overloadable; it is always a simple bit-wise copy.". С другой стороны, Clone является супертрейтом Copy, и наличие реализации Copy не мешает вызывать .clone() явно. Однако, в отличие от Copy, Clone::clone в принципе может вызывать любой код. Поэтому, в частности, технически замена в итераторной цепочке .cloned() на .copied() является ломающим изменением, даже если элементы итератора реализуют Copy.Продемонстрирую на примере:
use std::cell::Cell;Если запустить этот код, то он напечатает
struct Counter<'a>(&'a Cell<u32>);
impl Clone for Counter<'_> {
fn clone(&self) -> Self {
self.0.set(self.0.get() + 1);
Self(self.0)
}
}
fn main() {
let n = Cell::new(0);
let arr = [Counter(&n), Counter(&n), Counter(&n)];
arr.iter().cloned().for_each(drop);
println!("`Counter::clone` called {} times", n.get());
}
`Counter::clone` called 3 times. Теперь добавим к определению Counter аннотацию #[derive(Copy)] и допишем в main тот же код, что там есть, но с заменой .cloned() на copied():fn main() {
// ...
let n = Cell::new(0);
let arr = [Counter(&n), Counter(&n), Counter(&n)];
arr.iter().copied().for_each(drop); // изменение в этой строке
println!("`Counter::clone` called {} times", n.get());
}
Код теперь выводит:`Counter::clone` called 3 times
`Counter::clone` called 0 times
Берегите себя и не пишите, пожалуйста, в Clone::clone что-то помимо собственно клонирования.doc.rust-lang.org
Copy in std::marker - Rust
Types whose values can be duplicated simply by copying bits.
== Where to go to learn Rust in 2021
https://loige.co/where-to-go-to-learn-rust-in-2021/
отличный список со ссылками где и что почитать для изучения #rust
https://loige.co/where-to-go-to-learn-rust-in-2021/
отличный список со ссылками где и что почитать для изучения #rust
loige.co
Where to go to learn Rust in 2021
This article provides a list of free and paid resources to learn Rust in 2021 including books, blogs, videos, newsletters, podcasts, communities, exercises, workshops, and open source projects.
== High Velocity Kernel File Systems with Bento
https://www.usenix.org/system/files/fast21-miller.pdf
а-е. тут есть чему поучиться. как сделать фс на #rust
https://www.usenix.org/system/files/fast21-miller.pdf
а-е. тут есть чему поучиться. как сделать фс на #rust
Forwarded from Блог*
#prog #rust #моё
Меня тут один Олег™ попросил коротко рассказать о афинных типах в Rust. Что ж, рассказываю.
Аффинные системы типов — это системы типов, в которых объявленные значения можно использовать не более одного раза. Как и прочие ти́повые навороты, это позволяет писать более корректные программы путём перекладывания бо́льшего числа проверок на компилятор.
Для демонстрации практической пользы приведу пару примеров из стандартной библиотеки Rust:
1. std::sync::Mutex. Для корректной работы многопоточной программы требуется, чтобы доступ к совместно разделяемым изменяемым данным был должным образом синхронизирован. Один из способов достичь его — это защитить изменяемое значение мьютексом. Простой способ, обладающий, однако, существенным недостатком: очень просто забыть захватить блокировку перед тем, как получить доступ к значению (особенно если мьютекс защищает несколько переменных). Какое решение предлагает Rust?
Посмотрим на то, как создать мьютекс. Единственный способ создать мьютекс — это передать ему защищаемое значение. После этого получить доступ к разделяемому значению можно, только попытавшись захватить блокировку или же разрушив мьютекс, причём последнее можно сделать только в том случае, если поток (в смысле thread) единолично владеет мьютексом. Таким образом, несинхронизированный доступ исключён.
Другая возможная проблема с мьютексом связана с тем, что в большинстве языков программирования значения неявно копируются: нужно прилагать специальные усилия для того, чтобы удостовериться, что каждый из thread-ов получает один и тот же мьютекс, а не свою собственную копию (тут была шутка про Go, но она была настолько толстой, что Telegram не давал загрузить пост). В Rust это получается автоматически: нет методов, позволяющих получить копию мьютекса, поэтому расшарить можно только тот или иной вид указателя на мьютекс.
2. std::fs::File. Сборщик мусора помогает освобождать занятую память, но он не очень помогает с внешними ресурсами, в частности, файлами: закрыть файл обычно нужно сразу после того, как работа с ним окончена, а сборщик мусора никаких гарантий по времени закрытий файла не даёт. В стандартной библиотеке большинства языков программирования (даже с GC) есть отдельная функция, которая закрывает файл. Тем не менее, присутствие этой функции обнажает серьёзный изъян в системе типов: файл невозможно использовать после закрытия (также, как и до открытия, но обычно это не является большой проблемой), но это состояние никак не отслеживается в системе типов. Более того, дважды закрывать файл может быть попросту опасно: например, на Linux файл описывается файловым дескриптором — фактически, просто числом. После закрытия файла это же числовое значение может быть переиспользованно для другого файла, поэтому второе закрытия того же файлового дескриптора может привести к закрытию файла в другой программе!
Как эти проблемы обходятся в Rust? Если вы проверите API File, то... Вы не найдёте там метода close! Когда File выходит из области видимости, для него вызывается деструктор, который и закрывает файл. Т. к. явного метода закрытия файла в публичном API нет, единственный способ форсировать закрытие файла — это дропнуть файл (например, вызовом std::mem::drop). В силу того, что после этого получить доступ к файлу нельзя, возможность двойного закрытия статически запрещается.
Очевидно, аффинные типы не являются серебряной пулей. Каковы же недостатки? Конкретно в случае с File недостаток очевиден: закрытие файла может завершиться ошибкой, но закрытие посредством вызова деструктора не позволяет об этом узнать. Более сильные линейные типы (в которых каждое значение используется ровно один раз) позволили бы решить эту проблему, требуя явно вызывать close и таким образом давать доступ к возможным ошибкам, но это уже тема для другого поста.
Меня тут один Олег™ попросил коротко рассказать о афинных типах в Rust. Что ж, рассказываю.
Аффинные системы типов — это системы типов, в которых объявленные значения можно использовать не более одного раза. Как и прочие ти́повые навороты, это позволяет писать более корректные программы путём перекладывания бо́льшего числа проверок на компилятор.
Для демонстрации практической пользы приведу пару примеров из стандартной библиотеки Rust:
1. std::sync::Mutex. Для корректной работы многопоточной программы требуется, чтобы доступ к совместно разделяемым изменяемым данным был должным образом синхронизирован. Один из способов достичь его — это защитить изменяемое значение мьютексом. Простой способ, обладающий, однако, существенным недостатком: очень просто забыть захватить блокировку перед тем, как получить доступ к значению (особенно если мьютекс защищает несколько переменных). Какое решение предлагает Rust?
Посмотрим на то, как создать мьютекс. Единственный способ создать мьютекс — это передать ему защищаемое значение. После этого получить доступ к разделяемому значению можно, только попытавшись захватить блокировку или же разрушив мьютекс, причём последнее можно сделать только в том случае, если поток (в смысле thread) единолично владеет мьютексом. Таким образом, несинхронизированный доступ исключён.
Другая возможная проблема с мьютексом связана с тем, что в большинстве языков программирования значения неявно копируются: нужно прилагать специальные усилия для того, чтобы удостовериться, что каждый из thread-ов получает один и тот же мьютекс, а не свою собственную копию (тут была шутка про Go, но она была настолько толстой, что Telegram не давал загрузить пост). В Rust это получается автоматически: нет методов, позволяющих получить копию мьютекса, поэтому расшарить можно только тот или иной вид указателя на мьютекс.
2. std::fs::File. Сборщик мусора помогает освобождать занятую память, но он не очень помогает с внешними ресурсами, в частности, файлами: закрыть файл обычно нужно сразу после того, как работа с ним окончена, а сборщик мусора никаких гарантий по времени закрытий файла не даёт. В стандартной библиотеке большинства языков программирования (даже с GC) есть отдельная функция, которая закрывает файл. Тем не менее, присутствие этой функции обнажает серьёзный изъян в системе типов: файл невозможно использовать после закрытия (также, как и до открытия, но обычно это не является большой проблемой), но это состояние никак не отслеживается в системе типов. Более того, дважды закрывать файл может быть попросту опасно: например, на Linux файл описывается файловым дескриптором — фактически, просто числом. После закрытия файла это же числовое значение может быть переиспользованно для другого файла, поэтому второе закрытия того же файлового дескриптора может привести к закрытию файла в другой программе!
Как эти проблемы обходятся в Rust? Если вы проверите API File, то... Вы не найдёте там метода close! Когда File выходит из области видимости, для него вызывается деструктор, который и закрывает файл. Т. к. явного метода закрытия файла в публичном API нет, единственный способ форсировать закрытие файла — это дропнуть файл (например, вызовом std::mem::drop). В силу того, что после этого получить доступ к файлу нельзя, возможность двойного закрытия статически запрещается.
Очевидно, аффинные типы не являются серебряной пулей. Каковы же недостатки? Конкретно в случае с File недостаток очевиден: закрытие файла может завершиться ошибкой, но закрытие посредством вызова деструктора не позволяет об этом узнать. Более сильные линейные типы (в которых каждое значение используется ровно один раз) позволили бы решить эту проблему, требуя явно вызывать close и таким образом давать доступ к возможным ошибкам, но это уже тема для другого поста.
Forwarded from Блог*
#prog #rust #article
Очередная статья про обработку ошибок в Rust, да. Но полезная: ставит под сомнения и разбирает распространённые мнения об ошибках в Rust. В частности, разбирается совет "anyhow для приложений, thiserror для библиотек".
Очередная статья про обработку ошибок в Rust, да. Но полезная: ставит под сомнения и разбирает распространённые мнения об ошибках в Rust. В частности, разбирается совет "anyhow для приложений, thiserror для библиотек".
Unwoundstack
Rust Error Handling
Some thoughts on how to handle errors in Rust
Forwarded from Technologique
Some absolutely great software - a tools, written in Rust, which can improve your daily workflow and can help get things done faster:
Terminal emulator:
https://github.com/alacritty/alacritty
File managers:
https://github.com/ranger/ranger
https://github.com/ranger/ranger/wiki/Similar-software#hunter-rust
https://github.com/rabite0/hunter
#Rust
Terminal emulator:
https://github.com/alacritty/alacritty
File managers:
https://github.com/ranger/ranger
https://github.com/ranger/ranger/wiki/Similar-software#hunter-rust
https://github.com/rabite0/hunter
#Rust
GitHub
GitHub - alacritty/alacritty: A cross-platform, OpenGL terminal emulator.
A cross-platform, OpenGL terminal emulator. Contribute to alacritty/alacritty development by creating an account on GitHub.
Forwarded from Sysadmin Tools 🇺🇦
PGCat
PS: thanks @nosingularity for the link
#postgresql #postgres #sql #rust
PgBouncer rewritten in Rust, with sharding, load balancing and failover support.
https://github.com/levkk/pgcatPS: thanks @nosingularity for the link
#postgresql #postgres #sql #rust
Forwarded from Блог*
Forwarded from Блог*
#prog #rust #article
How (and why) nextest uses tokio, part 1
Или хороший пример того, как async может пригодиться в программе, которая вообще никак не связана с общением по сети.
How (and why) nextest uses tokio, part 1
Или хороший пример того, как async может пригодиться в программе, которая вообще никак не связана с общением по сети.
How (and why) nextest uses tokio
How (and why) nextest uses tokio ꞏ sunshowers
How my open source test runner uses async Rust.
Forwarded from Блог*
#prog #rust #article
How much does Rust's bounds checking actually cost?
What is the actual cost of all this extra bounds checking, though? There’s a little bit of prior art here <...> On the other hand, I wasn’t able to find an extensive analysis of the cost of pervasive bounds checking on a real, large, production Rust codebase with high performance sensitivity. I happen to work on one of those, so I figured it might be interesting to take a look at the cost of bounds checks in the hot path.
TL;DR: выкидывание всех этих проверок — даже с использованием запатченного rustc, который не генерирует инструкции с проверками индексации (что вообще-то unsound) — не делает программу быстрее и даже может сделать несколько медленнее.
How much does Rust's bounds checking actually cost?
What is the actual cost of all this extra bounds checking, though? There’s a little bit of prior art here <...> On the other hand, I wasn’t able to find an extensive analysis of the cost of pervasive bounds checking on a real, large, production Rust codebase with high performance sensitivity. I happen to work on one of those, so I figured it might be interesting to take a look at the cost of bounds checks in the hot path.
TL;DR: выкидывание всех этих проверок — даже с использованием запатченного rustc, который не генерирует инструкции с проверками индексации (что вообще-то unsound) — не делает программу быстрее и даже может сделать несколько медленнее.
Readyset | Drop-in SQL Caching for PostgreSQL and MySQL
Increase the scale of your PostgreSQL and MySQL deployment by up to 100x with Readyset - all without modifying your application code or database. Start using Readyset today for free!
Forwarded from Блог*
#prog #rust
Если ждать достаточно долго, то можно дождаться исполнения своего желания. В данном случае — желания разобраться с конкурентностью на низком уровне.
Небезызвестная Mara Bos опубликовала свою книгу: Rust Atomics and Locks: Low-Level Concurrency in Practice. Все главы можно прочитать бесплатно онлайн.
Если ждать достаточно долго, то можно дождаться исполнения своего желания. В данном случае — желания разобраться с конкурентностью на низком уровне.
Небезызвестная Mara Bos опубликовала свою книгу: Rust Atomics and Locks: Low-Level Concurrency in Practice. Все главы можно прочитать бесплатно онлайн.
marabos.nl
Rust Atomics and Locks by Mara Bos
Low-level Concurrency in Practice. This practical book helps Rust programmers of all levels gain a clear understanding of low-level concurrency. You'll learn everything about atomics and …
Forwarded from Блог*
#prog #rust #rustlib
schnellru — A fast and flexible LRU map
* Blazingly fast. Up to twice as fast as the
* Can be also used as an ordered map, with roughly the same performance as
* Customizable. Out-of-box can be limited by length or by memory usage, but supports custom limiters which can be made to limit the map by whatever you want.
* Tested, miri-clean, clippy-clean and fuzzed.
* Supports
schnellru — A fast and flexible LRU map
* Blazingly fast. Up to twice as fast as the
lru crate, and with less memory overhead.* Can be also used as an ordered map, with roughly the same performance as
indexmap, but with added support for O(1) removals without changing the element order (where indexmap only supports O(n) non-perturbing removals).* Customizable. Out-of-box can be limited by length or by memory usage, but supports custom limiters which can be made to limit the map by whatever you want.
* Tested, miri-clean, clippy-clean and fuzzed.
* Supports
no_std.