• В чем причина утечки памяти в программе на rust?

    @GeraZlo Автор вопроса
    Устранил утечку переписав большую страшную функцию, в замыкании на две маленькие, вынеся всю логику за пределы замыкания.

    Было:
    impl UserRssItemsFilter for FilterByLastRequestData {
        fn filter(&self, user: i64, rep: &String, item: &RssItem) -> bool {
            let key = format!("{} {}", user, rep);
            let r = self.last_request_cache.write(|db| {
                let last_request: DateTime<Utc> = if let Some(last_request_str) = db.get(&key) {
                    DateTime::parse_from_rfc2822(&last_request_str).unwrap().into()
                } else {
                    Utc::now() - Duration::days(2)
                };
                if last_request < item.created_date {
                    db.insert(key, item.created_date.to_rfc2822());
                    true
                } else {
                    false
                }
            }).unwrap();
            self.last_request_cache.save().unwrap();
            r
        }
    }


    Стало:
    impl UserRssItemsFilter for FilterByLastRequestData {
        fn filter(&self, user: i64, rep: &String, item: &RssItem) -> bool {
            let key = format!("{} {}", user, rep);
            let last_request = match  self.last_request_cache.read(|db| {
                match db.get(&key) {
                    Some(v) => Some(DateTime::parse_from_rfc2822(v).unwrap().into()),
                    None => None
                }
            }).unwrap() {
                Some(v) => v,
                None => Utc::now() - Duration::days(2)
            };
    
            if last_request < item.created_date {
                self.last_request_cache.write(|db| {
                    db.insert(key, item.created_date.to_rfc2822());
                }).unwrap();
                self.last_request_cache.save().unwrap();
                true
            } else {
                false
            }
        }
    }
    Ответ написан
    Комментировать
  • Как сформировать аргумент данного типа?

    @mikeyuriev
    Some((&[""], ""))
    или
    None

    Зависит о того, что вам надо. Почитайте про Option.
    Ответ написан
    Комментировать
  • Существуют ли фреймворки, позволяющие писать бекенд на rust+javascript?

    bingo347
    @bingo347
    Crazy on performance...
    Смотря что Вы понимаете под rust+javascript
    Если это проект на rust со вставками на js (например для ssr), то есть несколько вариантов:
    1. Рядом работают приложение на rust и приложение на node.js, общаются по tcp/udp/unixsock/etc.
    2. Интегрировать rust приложение как нативный аддон к node.js, общение через ffi, для этого есть neon.
    3. Внедрить js движок в приложение на rust, например есть байндинг к v8 из deno или гораздо более легковесный quick-js, правда байндинг пока сильно урезанный и не факт, что станет лучше, занимается им явно человек далекий от js. Я в свободное время пилю свою safe обертку для данного движка, моя цель как раз таки запуск ssr js фреймворков в rust приложениях, но что-то рабочее будет думаю не раньше октября.
    Ответ написан
    Комментировать
  • Rust unsafe, какие есть подводные камни и как подходить к дизайну C API?

    vabka
    @vabka Куратор тега Rust
    Не пудри себе мозги и возьми уже готовую безопасную обёртку над raylib
    https://crates.io/crates/raylib

    А гайд по работе с unsafe - это rustonomicon

    unsafe сам по себе просто позволяет использовать сырые указатели + вызывать другие unsafe функции.

    Безопасная обётка - это когда ты при помощи типов и всяких валидаций гарантируешь корректное использование.
    Вот пример из того что выше:
    use raylib::prelude::*;
    
    fn main() {
        let (mut rl, thread) = raylib::init()
            .size(640, 480)
            .title("Hello, World")
            .build();
    
        while !rl.window_should_close() {
            let mut d = rl.begin_drawing(&thread);
    
            d.clear_background(Color::WHITE);
            d.draw_text("Hello, world!", 12, 12, 20, Color::BLACK);
        }
    }

    Если для вас это магия, то тогда нужно чуть глубже изучить Rust и посмотреть в исходники.

    На будущее: не пишите огромную портянку текста с кучей вопросов, а пишите только то что непосредственно относится к основному вопросу.
    Другие вопросы задавайте отдельно.
    Ответ написан
    Комментировать
  • Как запустить bat файл из кода Rust?

    vabka
    @vabka Куратор тега Rust
    std::process::Command
    Находится буквально по запросу: "rust start process"
    Ответ написан
    Комментировать
  • С чего начать изучение языка?

    Kozack
    @Kozack Автор вопроса
    Thinking about a11y
    Комментировать
  • С чего начать изучение языка?

    vabka
    @vabka Куратор тега Rust
    Почему не rustbook?
    Для его понимания никакой ЯП знать не нужно
    Ответ написан
    Комментировать
  • Как безболезненно перейти с Python на Rust?

    Как безболезненно перейти с Python на Rust?

    Учиться, учиться, учиться.
    1) Python медленный

    Питон на удивление быстрый, особенно если использовать PyPy, а сильные тормоза возникают только в особых случаях.
    2) В python нет адекватного управления памятью

    Автоматический GC - это один из самых адекватных способов управления памятью, который только придумывало человечество.
    3) В python мне приходится испльзовать кучу мегабайт библиотек (я чувствую себя тупым и бесполезным при импортировании библеотек)

    А вы импортируйте их с мыслью "я не хочу тратить кучу времени на реализацию этого всего с нуля"
    В расте вам точно также придётся импортировать кучу библиотек, как и в любом другом языке, где есть библиотеки.
    4) Python кажется игрушечным языком

    Зря так думаете. Python очень мощный.
    5) Python не подходит род микроконтроллеры (micropython - просто игрушка)

    Раст+МК для новичков тоже очень страшная вещь - посмотрите на вопросы от товарища eegmak, например, чтобы в этом убедиться.
    Micropython - вполне себе production ready инструмент для тех случаев, когда его хватает, и не нужно ужиматься в очень дешёвые чипы.
    6) Проблемы из-за GIL'а

    С какими именно проблемами вы столкнулись на практике?)
    Скорее всего, их можно решить и менее радикальными методами.

    ИМХО: вы услышали от кого-то что Rust-топ язык, а Python - игрушечный, а настоящие программисты используют ручное управление памятью и сами реализовывают всякие сложные алгоритмы и протоколы.
    Хотя обычно ещё пишут, что настоящие программисты пишут только на C, только в виме, и никогда не ищут ответы на русскоязычных форумах.

    Если я прав - задумайтесь ещё раз, какую именно вашу проблему может решить раст, которую не может решить Python.

    Если я вас не отговорил - берите rustbook (лучше способа не придумали ещё).

    Если хочется перейти на другой язык, не обязательно раст - посмотрите в сторону других языков со сборкой мусора - например C#, Go, или D. Их все можно использовать в том числе и на МК, с разной степенью извращений.
    Ответ написан
  • Хайп вокруг ЯП Rust и C?

    vabka
    @vabka Куратор тега Rust
    По порядку:
    Насколько критичной проблемой для программиста является ручное управление памятью, которое называют недостатком языка Си?

    С неправильным управлением памятью связано очень много ошибок. Например в хроме вроде около половины CVE с этим связано. Ещё можно вспомнить HeartBleed в OpenSSL, который тоже связан с неправильным управлением памятью.

    (Дальше какое-то ужасно длинное предложение, которое я разбил на части)
    Новый язык программирования Раст, как заявляют, лишен этого недостатка

    Да
    разве общее число ошибок не перераспределяется на другие недостатки

    1. Самые сложные в исправлении ошибки - кривое управление памятью и многопоточность, обе их Rust Решает
    2. Нет, ошибки не перераспределяются, это же не тараканы.
    являются ли ошибки с памятью ошибками программиста

    Если управление памятью ручное, то это ошибки, которые допустил разработчик.
    Если управление памятью автоматическое (хоть через GC, хоть через Borrow checker), то это ошибка компилятора/рантайма/языка.

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

    Не обязательно.

    В целом вопрос очень абстрактный и является скорее поводом для дискуссий. Попробуйте дать более конкретный пример, где ошибка управления памятью превращается в какую-то другую ошибку.
    Ответ написан
    Комментировать
  • Как скачать Rust IDE JetBrains на ubuntu?

    vabka
    @vabka Куратор тега Rust
    Ставишь Jetbrains toolbox: https://www.jetbrains.com/toolbox-app/ - через него ставишь clion (платно, но зато есть дебаг) или intellij idea community (бесплатно, но без дебага)
    А потом плагин: https://intellij-rust.github.io/
    Ответ написан
    Комментировать
  • Какой выбрать язык для работы с 3D - Rust или C++?

    Про C++ не скажу, но у rust есть нюансы:
    1. Все эти приколы с borrow checker'ом, которые, я думаю, с 3д ещё чаще будут возникать из-за сложных структур данных.
    2. Может не хватить каких-то библиотек - могут оказаться только голые обёртки над си (а то и вообще придётся их генерить), что тоже не очень удобно.

    Но лично я не вижу в этом большой проблемы, тк раст сильно удобнее, чем C++, а побороть компилятор сильно проще, чем кажется.

    Для opengl, vulkan, directx, winapi уже есть удобные обёртки, и их можно найти на crates.io
    Ответ написан
    1 комментарий
  • Как вернуть значение из поля структуры в методе?

    vabka
    @vabka Куратор тега Rust
    попробуйте написать
    pub struct MimeType {
        extension: String,
        charset: String,
    }
    
    impl MimeType {
        pub fn new(extension: String, charset: String) -> MimeType {
            return MimeType { extension, charset };
        }
    
        pub fn extension(&self) -> &String {
            return &self.extension;
        }
    
        pub fn charset(&self) -> &String {
            return &self.charset;
        }
    }


    строкой владеет MimeType, так что нельзя просто так взять её - нужно либо брать ссылку, либо клонировать.
    Обратите ещё внимание на телеграм чаты сообщества - там гораздо проще и быстрее получить ответ на простой вопрос:
    https://t.me/rust_beginners_ru
    https://t.me/rustlang_ru
    Ответ написан
    2 комментария
  • Какое выбрать кресло для программиста?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Эргономичное посоветую. А в этой области за последние лет 10 ничего особенно не поменялось - Herman Miller Aeron.

    Дома уже лет 6 использую Duorest Alpha 80H. Не Аэрон конечно, но всё равно очень доволен.

    То, что у вас по ссылке - это не кресло для программиста, а просто кресло, причём уровня офисного ширпотреба.
    Ответ написан
    2 комментария
  • Как ограничить тип T примитивными типами f32 и f64?

    bingo347
    @bingo347
    Crazy on performance...
    Ограничить дженерик-тип можно только типажами (traits).
    Что Вы хотите сделать? Какие методы f32 и f64 Вам нужны?
    Возможно данные методы уже реализованы в типажах стандартной библиотеки - тогда нужно ограничивать их суммой.

    Другой вариант, сделать свой типаж, ограничить дженерик тип им, имплементировать этот типаж для f32 и f64
    Имплементация должна представлять обертки над нужными действиями

    UPD: если нужно ограничение дженерик, на использование метода exp у f32 и f64:
    Типаж-контракт на метод exp:
    trait Exp {
        fn exp(self) -> Self;
    }
    
    impl Exp for f32 {
        fn exp(self) -> Self {
            <f32>::exp(self)
        }
    }
    
    impl Exp for f64 {
        fn exp(self) -> Self {
            <f64>::exp(self)
        }
    }


    так же можно воспользоваться следующим крэйтом:
    https://crates.io/crates/num
    Ответ написан
    2 комментария
  • Вопрос про владение в Rust, что не так?

    keksmen
    @keksmen
    Just a programmer
    Дело в том, что, как и сказал компилятор, вы пытаетесь использовать значение после его перемещения.
    Рассмотрим участок кода.
    // умножаем  слой на предыдущую  матрицу
    buf = v.mat_mul(&buf);
    // результат записываем в вектор 
    result.push(buf);

    На первой строчке вы определяете новое значение переменной. На второй - перемещаете значение в вектор.
    После перемещения значение в переменной считается недействительным, т.к. его использование может нарушить безопасность памяти. Это один из основных принципов семантики владения.

    Отвечая на ваш второй вопрос: да, клонирование - то, что вам нужно использовать в данном случае.
    // умножаем  слой на предыдущую  матрицу
    buf = v.mat_mul(&buf);
    // результат записываем в вектор 
    result.push(buf.clone());


    Однако, клонирование - операция дорогая. Учитывая, что для умножения нужна всего-лишь иммутабельная ссылка на матрицу, мы можем переписать код следующим образом:
    // вектор, где будут хранится  произведения матриц
    let mut result = vec![];
    
    for v in layers {
    	// пытаемся достать предыдущую матрицу
    	let previous_matrix = match result.last() {
    		Some(last) => last,
    		// а если таковой нет - ей станет входная
    		None => &input,
    	};
    	// умножаем  слой на предыдущую (или входную) матрицу
    	let next_matrix = v.mat_mul(previous_matrix);
    	result.push(next_matrix);
    }


    Метод Vec::<T>::last возвращает Option<&T>, которая содержит ссылку на последний элемент ветора, если таковой существует. Его сложность O(1), поэтому по поводу ухудшения производительности можно не беспокоиться.
    Это именно то, для чего и создавалась переменная-буфер. Теперь нам не нужно производить лишнее клонирование.
    Ответ написан
    1 комментарий
  • Почему минимальный размер приложения такой большой?

    Tyranron
    @Tyranron
    Избитая тема, которая уже подымалась и изучалась не один раз. Достаточно сделать: https://www.google.com/search?q=rust+binary+size и сразу попадаем на статью Rustlog: Why is a Rust executable large?. Настоятельно рекомендую к прочтению, хоть она и слегка устарела (Rust больше не использует jemalloc по умолчанию), но вопрос там разобран крайне детально.

    Если коротко, то в Ваш бинарь попадают:
    1. Если собирали не в release mode, то debug-символы.
    2. Аллокатор, либо код-клей для системного аллокатора.
    3. Код для panic unwinding (в том числе и libbacktrace).
    4. Части libstd Rust'а, даже если Вы их не используете.

    Если стоит задача минимизировать бинарь Rust (под всякий embedded, к примеру), то обычно делают #![no_std], юзают мини-аллокаторы, делают panic = abort и идут на другие лишения.
    Ответ написан
    3 комментария
  • Правда ли, что в области высокопроизводительных приложений за Rust'ом будущее?

    @inv2004
    1) Правильнее сказать, что у Rust есть потенциал в далёком будущем заменить высокопроизводительный C++.

    2) Rust находится на приличном уровне производительности относительно плюсов, местами даже обгоняет, как пример "наколенных" тестов, можно посмотреть сюда: https://benchmarksgame-team.pages.debian.net/bench...

    3) Сможет ли он заменить - это сложный вопрос, может быть да, а может и нет, тут, ИМХО, несколько факторов.
    3.1) если говорить о максимальной оптимизации (что уже требует unsafe) - то именно в unsafe-коде преимуществ относительно C++ не видно.
    3.2) если сравнивать с популярными языками типа Java/C#/Go, то часто они не так сильно отстают от раста и даже плюсов чтобы переходить на более сложный язык.
    3.3) Язык частично определяет его популярность из-за многих факторов помимо производительности. У раста высокий порог вхождения и большая сложность написания, зато большая надёжность. Если он будет непопулярным, пусть даже быстрым, то возможно ниша останется за плюсами, если вдруг начнёт набирать популярность по каким-то причинам - то возможно и заменит.

    Как верно написали - лет через 10 посмотрим. Немного другой вопрос что надо делать сейчас чтобы шансы заменить выросли.
    Ответ написан
    1 комментарий
  • Как удалить первый элемент из вектора в Rust?

    0xD34F
    @0xD34F
    Есть же метод remove - просто указываете индекс, ну и всё.
    Ответ написан
    1 комментарий
  • Подойдёт ли Rust для 3D игр?

    vahe_2000
    @vahe_2000
    arewegameyet
    Rust потенциально является идеальным языком для разработки игр, но экосистема еще очень молода

    arewegameyet.com/#eco
    Ответ написан
    Комментировать
  • Кто может объяснить разницу между hyper и Tokio в Rust'е?

    hrls
    @hrls
    HTTP – протокол. Tokio – библиотека для написания сетевого кода, любого. Но парсить HTTP Tokio не умеет. Для этого есть Hyper – библиотека для написания HTTP серверов и клиентов. HTTP сервер на Hyper будет использовать Tokio для работы с соединениями, а парсить HTTP будет уже Hyper.
    В модели клиент-сервер очевидно есть клиент и сервер. HTTP клиент это все тот же сокет, только уже не серверный. Поэтому и тут Hyper может создавать запросы и парсить ответы. И также, возможно, для взаимодействия с сетью используя Tokio.
    Ответ написан
    Комментировать