• Как правильно принимать данные в потоках?

    bingo347
    @bingo347
    Crazy on performance...
    Arc нужно клонировать до move в замыкание, которое запускается на потоке. Если данные используются только на чтение, то этого будет достаточно, если данные будут меняться из нескольких потоков, то следует дополнительно обернуть их в Mutex/RwLock (или из std::sync или из библиотеки parking_lot).
    use std::sync::Arc;
    
    fn main() {
        let data = Arc::new(vec![1, 2, 3]);
    
        let thread_1 = std::thread::spawn({
            let data = Arc::clone(&data);
            move || {
                println!("Thread 1 data: {:?}", data);
            }
        });
    
        let thread_2 = std::thread::spawn({
            let data = Arc::clone(&data);
            move || {
                println!("Thread 2 data: {:?}", data);
            }
        });
    
        thread_1.join().unwrap();
        thread_2.join().unwrap();
    }

    Передавать так можно хоть вектор, хоть свою структуру, главное чтоб у типа был трейт Send и лайфтайм 'static (все владеющие типы имеют такой лайфтайм).
    Так как передаем мы по сути Arc, то Send должен быть у него, а он будет для любого содержимого реализующего Sync.

    Я обернул создание отдельного потока в функцию и так передавал в поток данные. Удобно, что такую функцию могу вынести в отдельный файл-модуль. Но не смог такое сделать динамически в цикле для группы потоков. Хочу подойти к варианту, когда поток, который закончил выполнение своего кода (раньше других), можно опять запустить из main и передать ему новую задачу (новые данные), - структуру данных, которую привёл в основном вопросе.
    Если правильно понял, то Вам нужен thread pool. Можно использовать из библиотеки rayon: https://docs.rs/rayon/1.7.0/rayon/struct.ThreadPoo...
    Но если хочется повелосипедить, можно нечто такое сделать:
    use std::{
        sync::{
            mpsc::{self, Sender},
            Arc, Mutex,
        },
        thread::{self, JoinHandle},
    };
    
    type Task = Box<dyn FnOnce() + Send + 'static>;
    
    pub struct ThreadPool {
        handles: Vec<JoinHandle<()>>,
        task_sender: Sender<Task>,
    }
    
    impl ThreadPool {
        pub fn new() -> Self {
            let threads_count = thread::available_parallelism()
                .map(|n| n.get())
                .unwrap_or(2);
            let (task_sender, task_receiver) = mpsc::channel::<Task>();
            let task_receiver = Arc::new(Mutex::new(task_receiver));
            let mut handles = Vec::with_capacity(threads_count);
            for _ in 0..threads_count {
                let task_receiver = Arc::clone(&task_receiver);
                handles.push(thread::spawn(move || loop {
                    let task_receiver = task_receiver.lock().unwrap_or_else(|e| e.into_inner());
                    let Ok(task) = task_receiver.recv() else {
                        return;
                    };
                    drop(task_receiver);
                    task();
                }));
            }
            Self {
                handles,
                task_sender,
            }
        }
    
        pub fn spawn_task<F: FnOnce() + Send + 'static>(&self, f: F) {
            self.task_sender.send(Box::new(f)).expect("All threads ended");
        }
    
        pub fn join(self) -> thread::Result<()> {
            drop(self.task_sender);
            for handle in self.handles {
                handle.join()?;
            }
            Ok(())
        }
    }
    
    #[test]
    fn thread_pool() {
        let pool = ThreadPool::new();
        for i in 0..500 {
            pool.spawn_task(move || {
                println!("Task {} working on thread {:?}", i, thread::current().id());
            });
        }
        pool.join().unwrap();
    }
    Ответ написан
    3 комментария
  • Как работает locals() в python?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Python
    Седой и строгий
    Прежде всего, в pydoc-комментарии функции locals есть сноска о том, что синхронизация возвращённого функцией словаря с состоянием переменных не гарантируется и зависит от реализации. Конкретно в CPython в данный момент такой синхронизации не происходит потому, что locals получает значения переменных из фрейма стека, копирует в новый словарь и возвращает его. Сделано так, как ни парадоксально, для производительности.
    Ответ написан
    Комментировать
  • Почему в Rust использую Tokio?

    @D3lphi
    Потому что она реализует то, чего нет в стандартной библиотеке - асинхронный рантайм. Если писать сетевое приложение без токио, то придется плодить по отдельному потоку на каждый сетевой коннекшен. (на самом деле, речь идет про любой i/o, к которому чтение/запись файлов тоже относится) Каждый из этих потоков большую часть времени будет заблокирован в ожидании завершения сететвого вызова (передачи или приема данных). Однако, операционная система при разблокировке этих тредов будет постоянно переключать контекст для каждого потока и тратить процессорное время.
    Асинхронный подход позволяет обойтись лишь сравнительно небольшим пулом потоков, на которые токио рантайм будет распределять таски (грин треды) и, таким образом, экономить процессорное время.
    Ответ написан
    9 комментариев
  • Почему в Rust использую Tokio?

    sergey-gornostaev
    @sergey-gornostaev
    Седой и строгий
    Rust currently provides only the bare essentials for writing async code. Importantly, executors, tasks, reactors, combinators, and low-level I/O futures and traits are not yet provided in the standard library. In the meantime, community-provided async ecosystems fill in these gaps.

    There is no asynchronous runtime in the standard library

    Из документации.
    Ответ написан
    Комментировать
  • Подойдет ли базовый MacBook Air M1 8/256 для web разработки?

    Не верьте хайповым видео о том, что его вам хватит для разработки. Сама машинка в плане качества и производительности просто прекрасна. Я являюсь владельцем M1 Pro 16/512. Как раз занимаюсь веб-разработкой.
    - Процессор этот смог бы ещё долго быть конкурентным. Тут проблемы нет.
    - Даже маленький размер диска совсем не проблема, потому что можно купить внешний диск, а т.к. у нас Thunderbolt, то вы практически не будете ощущать недостатка скорости. Внутренний SSD состоит из двух чипов, из-за этого диск работает быстрее, чем на M2 Air, где только один чип.
    - Самая главная проблема, которая хоронит этот компьютер для какой-либо серьезной разработки - это память... 8 Гб никуда не годится. Мне 16 впритык, куда уж там 8. Когда вы откроете браузер, IDE, запустите Docker, запустите автоматическую сборку при изменениях файлов и т.д и т.п., а потом включите Activity Monitor, то вы увидите то, что вам не покажут радостные хайпожоры, расхваливающие этот Мак именно как инструмент разработки. Увидите вы жуткий размер swap и график Memory Pressure жёлтого или красного цвета. Это означает, что памяти уже сильно не хватает.

    Поэтому, брать стоит только 16 Гб или больше. Я бы очень посоветовал не брать ноуты на Windows. Это дрянь. Автономность привязывает вас к розетке, с качеством сборки очень трудно угадать, да я бы не взял винбук из-за одного только Маковского трекпада, который является чуть ли не произведением искусства. На винбуках близко таких нет, даже на самых дорогих.

    В каких случаях можно брать M1 Air 8/256?
    Повторюсь, сам компьютер великолепен. Лучше печатной машинки за эти деньги вы не найдете. Он прекрасен. Если у вас уже есть что-то мощнее, то его можно взять именно как печатную машинку, которую везде таскать с собой.
    Но как только вы выйдете за пределы печатной машинки, нехватка памяти будет вас напрягать. Тем более, нельзя говорить ни о какой перспективе.

    PS. Почитайте каменты к моему посту. Возможно, этот вариант подойдёт.
    Ответ написан
    8 комментариев
  • Как написать сервер для хранение файлов на python?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Python
    Седой и строгий
    Выучить Python, изучить сети, базы данных, фреймворки и многое другое, а потом написать код сервера.
    Ответ написан
    Комментировать
  • Какой смысл ставить мощный Wi-Fi модуль в ограниченный роутер?

    vabka
    @vabka
    Токсичный шарпист
    Как минимум из-за того что не всякий роутер будет подключен к интернету кабелем.
    Конкретного у этого заявлена поддержка mesh-сетей. => К кабелю можно подключить роутер подороже и с нормальными портами, а вот этот недорогой использовать для расширения покрытия.

    мощный Wi-Fi модуль

    А кто тебе сказал, что там мощный wifi модуль?

    PS:

    Как показывает практика, даже в роутерах с WAN/LAN портами скоростью до 100 Мбит/с (если по тарифу 100 Мбит/с) есть смысл в поддержке стандарта 802.11ac Wi-Fi 5 GHz. Так как по Wi-Fi в диапазоне 2.4 GHz практически нереально выжать 100 Мбит/с. А в диапазоне 5 GHz без проблем можно получить эту скорость.


    А ещё тут другие отвечающие правильно заметили, что в локальной сети устройства между собой тоже могут общаться, хотя лично мне кажется, что для дома это не очень актуально (тот же nas я ни разу не видел, чтобы подключался по wifi, а не кабелем)
    Ответ написан
    Комментировать
  • Реальны ли SIM-карты со статическим IP для видеокамер?

    @Drno
    Потому что это выдают только юр лицам. И не все операторы

    Проще впн сеть организовать и не париться
    Ответ написан
    5 комментариев
  • Почему метод strip в Python так работает?

    @U235U235
    В документации по этому поводу ясно сказано, что аргумент функции - набор (set) символов, которые будут удалены в конце исходной строки.
    Ответ написан
    Комментировать
  • Как работает динамическое прямое соединение для торрент-клиентов?

    @SunTechnik
    https://ru.m.wikipedia.org/wiki/BitTorrent
    Есть torent-tracker, (с белым ip) где регистрируются клиенты и сообщают свои параметры.
    Так как протокол udp без установления соединения, то можно открыть порт через Nat, послав пакет на известный белый ip, после чего другой клиент может слать данные на этот открытый udp порт. (читать про Tun/stun)

    Но в любом случае нужен посредник с белым ip, для регистрации и пробития NAT.
    Ответ написан
  • Как избежать дубликации кода реализуя Trait'ы в Rust?

    bingo347
    @bingo347
    Crazy on performance...
    Написать derive макрос. Правда стоит соизмерить трудозатраты.
    Или написать обычный декларативный макрос (не так гибко как derive, но написать проще).

    А вообще, Rust не Java/C#, trait - не интерфейс.
    Если приведете не абстрактные примеры, вполне возможно, что задача решается проще.
    Ответ написан
    Комментировать
  • MacBook Air 13 M1/8/256 или Honor MagicBook 16 R5/16/512?

    xez
    @xez Куратор тега Железо
    TL Junior Roo
    Надо эир брать на эпловом процессоре, но на 16гб минимум.
    Ответ написан
    3 комментария
  • Обязателен ли web-server (NGINX) для Actix Web?

    bingo347
    @bingo347
    Crazy on performance...
    Кэширование, сжатие, https все же лучше на nginx переложить
    Ответ написан
    Комментировать
  • Почему в моем тесте go быстрее c?

    vabka
    @vabka
    Токсичный шарпист
    1. А почему оптимизации в GCC не включены?

    2. Код не эквивалентный. Зачем ты меряешь скорость printf?

    3. Почему всего 1 прогон? Может 3 секунды - входит в твою погрешность?
    Прогони хотябы по 100 раз и посчитай отклонение
    Ответ написан
  • Как установить срок действия пароля в Django?

    @Everything_is_bad
    Задача элементарная, добавь юзеру поле когда был задан пароль, потом добавь проверку на разницу этой даты с текущей. Зачем сюда приплетать allauth, непонятно.

    Существует ли готовое решения
    все готовые решения ищутся через гугл или на djangopackages. Давай научу тебе как искать в гугле, сначала открываешь его, потом прям так и вбиваешь "django user password expiration"
    Ответ написан
    4 комментария
  • Как сделать collect в кортеж?

    vabka
    @vabka
    Токсичный шарпист
    Кортеж имеет фиксированный размер и по тому просто так collect сделать нельзя.
    Тут тебе три варианта:
    1. Вроде в itertools есть реализации collect для небольших гомогенных кортежей.
    2. Делай collect в Vec и бери элементы из него
    3. Сделай два раза next на итераторе

    Код

    раз
    fn main() {
        let items = [1,2];
        let mut iter = items.into_iter().map(|x|5+x);
        let a = iter.next().unwrap();
        let b = iter.next().unwrap();
        println!("{a} {b}");
    }


    Два:
    fn main() {
        let items = [1,2];
        let [a,b] = items.map(|x|5+x);
        println!("{a} {b}");
    }


    Три:
    use itertools::Itertools; // 0.9.0
    
    fn main() {
        let items = [1,2];
        let (a,b) = items.iter().map(|x|5+x).next_tuple().unwrap();
        println!("{a} {b}");
    }

    Ответ написан
    4 комментария
  • Почему нельзя/можно писать бизнес-логику в sql?

    php666
    @php666
    PHP-макака
    Аргумент о том, что будем менять БД не подходит, БД менять ближайшие 10 лет не собираемся
    этот аргумент кочует лет 20, причем не только в отношении БД, а вообще всего.

    В PHP, например, абстракция PDO - почти такой же надуманный предлог, мол, а если база поменяется?

    Вот когда поменяется база, наймут новых разработчиков и они будут заново пилить и переписывать. Потому, что ПО ФАКТУ со сменой базы меняется всё - начиная с формата получения данных в клиентском коде и заканчивая теми участками, где используются какие-то фитчи конкретной СУБД, как, например, в MySql ONLY_FULL_GROUP_BY без которого SQL на другой базе попросту не сработает или функции, специфичные для бывшей/текущей БД.

    И что там будет через 10 лет не известно, проект либо раньше загнётся, либо его перепишут с нуля. В ином случае, если проект будет большой, никто его не будет переписывать через внедрение другой СУБД, никогда такого маразма не видел, это всё равно, что менять фундамент у здания - легче новое построить с учётом новых требований.

    Между тем, адепты не писать логику в БД почему-то тихо "игнорируют" такие вещи, как внешние ключи и такие вещи как ON DELETE CASCADE с удовольствием используют, а не пишут цикл перебора с методом delete для каждой из связанных сущностей.
    Ответ написан
    3 комментария
  • Как работает в данном примере декорирование?

    Maksim_64
    @Maksim_64
    Data Analyst
    Не очень понятно, а что не понятно. Передается объект класса в функцию, ты зачем назвал параметр функции func а передаешь туда объект класса. Вот здесь result = func(*args, **kwargs) ты инициализируешь экземпляр класса, затем возвращаешь его да и все, MyClass у тебя стала функцией которая возвращает экземпляр класса. Ну добавь там чего нибудь например.
    def f():
        return 100
        
    def decor(func): 
        def _wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            result.complex_calculation = f
            return result
        return _wrapper 
    
    class MyClass:
        def complex_calculation(self):
            return 42
    
    MyClass = decor(MyClass)
    
    my_obj = MyClass()
    
    print(my_obj.complex_calculation())

    Твой метод вернет, не 42, а 100. Или объяви метод какой-нибудь которого нет.
    Ответ написан
  • Как мне убрать несколько символов из tuple?

    sergey-gornostaev
    @sergey-gornostaev Куратор тега Python
    Седой и строгий
    Изучать самые основы языка.
    Ответ написан
    4 комментария
  • Что планирует ОС - потоки или процессы?

    jcmvbkbc
    @jcmvbkbc
    "I'm here to consult you" © Dogbert
    Из всего изученного стало понятно, что процессы - это некие "контейнеры", содержащие id, статус, instruction pointer, значение регистров, открытые файлы и другие данные контекста.

    Вот уже по этому предложению видно, что понятно не стало. instruction pointer и значения регистров -- свои у каждого потока.

    какую роль в планировании играют процессы?

    Никакой.

    Для чего они нужны?

    Для учёта ресурсов и создания изолированных адресных пространств.

    Как планировщик ОС работает с процессами?

    Никак.

    Моя единственная догадка в том, что планировщик как бы "заглядывает" в каждый процесс и уже там работает с потоками.

    Не нужно ему никуда заглядывать. У него есть списки потоков находящихся в разных состояниях, а планирование заключается в перемещении потоков по этим спискам.
    Ответ написан
    9 комментариев