Linker Unsafe
220 subscribers
182 photos
24 videos
18 files
859 links
Собираю ржавые и лямбдообразные новости, прикольные цитатки с форумов, ссылки на статьи и всё такое. В-общем, сюда я тащу такие крупицы, которые мне будет жаль потерять в цифровой бездне. Возможно, они покажутся интересными и вам.

Фи сюда: @nlinker
Download Telegram
Forwarded from Kai Ren
2. Касательно божественности CSP, акторов, асинхронщины, конкурентности и многопоточности.
Я не знаю почему так происходит, но у большинства Go'шников почему-то святая уверенность в превосходстве дизайна и реализации конкурентности в Go над чем бы то ни было. Когда на самом же деле, несмотря на действительно матёрую под-капотную реализацию (снимаем шляпу перед Дмитрием Вьюковым), это очень жёсткий компромис в плане дизайна для наиболее типовых ситуаций.
Меня забавляет, что Go'шники повторяю постоянно мантру "Concurrency is not parallelism", но если попросишь Go'шника написать тебе параллельный алгоритм, он побежит городить лабуду из каналов и sync.WaitGroup, но не потому что он глупый, а потому что сам язык Go и его платформа не дают Вам возможности писать параллельный код, а только конкурентный. Вы не можете гарантировать кол-во используемых реальных потоков ОС для той или иной задачи, ибо за Вас это решает внутренний планировщик. В Rust же идеология - не ограничивать в возможностях, потому многопоточность может использоваться как для конкурентности (см. crossbeam), так и для параллелизма (см. rayon).
Аналогично и с асинхронностью. За счёт того, что в Go смешались в кучу асинхронность, многопоточность и конкурентность, у Go'шников, как правило, нет понимания в плане разделения задаче на IO-bound и CPU-bound. Для них это всё одно и то же, и этими вопросами вместо них занимается планировщик горутин, далеко не всегда оптимальным образом. В Rust же вполне себе внятное разделение: IO-bound решай асинхронщиной, хоть поверх нескольких тредов, хоть поверх одного, CPU-bound решай синхронным многопотоком и/или векторизацией. Причём Rust стремится дать Вам возможность полностью выбирать ожидаемые гарантии, и тот же runtime крейт позволяет Вам выбрать желаемую под-капотную реализацию асинхронного движка на Ваш вкус, ведь те же тредпулы бывают с разными гарантиями производительности для разных задач.

Касательно того, что CSP в Go удобный - тоже с Вами не соглашусь. Как ни смешно, но отсутствие дженериков полностью убило удобство CSP в Go, ибо почти полностью убило создание вменяемых переиспользуемых абстракций. Шаг в лево, шаг в право, от стандартного "прочитать с канала"/"записать в канал", и сразу куча граблей и головняка. Вот несколько типовых моментов:
- В Go есть buffered и unbuffered каналы, buffered каналы имеют максимальный размер, а что мне делать, если мне нужен безразмерный канал и чтобы пишущий в канал никогда не блокировался и данные никогда не выбрасывались? Только пилить свою реализацию через interface{}, либо писать каждый раз руками. Причём, как раз за счёт того, что каналы не являются библиотечным типом, а гвоздями запаяны в сам язык, возникает куча трудностей, и не просто написать незабагованную реализацию безразмерного канала не так уж и тривиально, но и даже использовать её правильно нужно постараться: https://github.com/eapache/channels/issues/27
Скажите безразмерные каналы никому не нужны, потому что именно Вы их никогда не использовали? Real-world Go приложения с Вами не согласятся: https://github.com/kubernetes/ingress-nginx/pull/2082
В Rust есть crossbeam-channel крейт. Он не вшит в язык, но при этом лучше Go'шных каналов и в плане производительности, и в плане удобства использования.
- Есть 1000 ссылок, нужно каждую обработать определенным образом, но так, чтобы в один момент времени обрабатывалось не более 5 одновременно. Что делаем в Go? Правильно: создаём канал с буфером 5 на подачу ссылок, стартуем 5 горутин на обработку, которые сосут ссылки из этого канала, обрабатывают и складывают результат в другой канал, ну и, в зависимости от других условий sync.WaitGroup для синхронизации, чтобы всё довыполнялось. Надо ли говорить, что в 90% случаев были ошибки в реализации этого дела, особенно когда код писался джунами? В Rust же просто используешь futures_unordered() и горя не знаешь.
Forwarded from Kai Ren
Касательно акторов, то это просто чуть более высокоуровневая абстракция, которая удобна в ряде случаев, и не живёт отдельно от футур и асинков, но построена поверх них и вполне себе с ними сосуществует удобным образом. Кстати, реализации акторов есть и в Go прямо поверх CSP.
Forwarded from Kai Ren
3. Чего на Rust написано серьезного и какое у него будущее.
Rust уже активно используется большими компаниями. Firecracker от Amazon, libra от Facebook, fuchsia от Google, deno от Раяна Даля (кстати отказался от Go в пользу Rust), внутренне используется в Dropbox, CloudFlare, и, кажись, Microsoft Azure. Это только что сразу на уме всплыло. С каждым готом всё больше набирает популярность.
Нытьё про то, что язык игрушечный и никому не нужный, и ничего на нём не написано, я уже слышал и про Go ещё 3-4 годна назад, когда уже был Docker и HashiCorp'ы наваяли уже кучу всякого не нём, что использовалось в продакшене многими. Так что в будущем Rust у меня никаких сомнений нету.
Forwarded from Kai Ren
В заключение:
Если Вам тема Rust интересна именно в плане разработки веб-бекендов, то советую либо вникать в тему глубже и разбираться почему сделано так, а не иначе, и почему ситуация такова, а не кидаться мнениями со "своего болота" в стиле "я привык в Go делать так, почему в Rust не так? Фу какой Rust нихароший...". Либо же просто вернуться к Rust через годика 2, когда async story в Rust не просто стабилизируется до конца, но заматереет, да ещё и подтянется экосистема.
Forwarded from Peter Sovietov
Краткий обзор компилятора Go в двух частях от известного специалиста Eli Bendersky https://eli.thegreenplace.net/2019/go-compiler-internals-adding-a-new-statement-to-go-part-1/
Forwarded from ọzkriff
есть несколько начинаний для коллективного ревью зависимостей, например reddit.com/r/rust/comments/bhjjln/cargo_crev_verify_deps_best_security_view_into но прошлые местные обсуждения сходились на том, что в таком виде оно не взлетит
Forwarded from Kai Ren
Вопрос про Go? Не считаю его простоту положительной чертой. Она позволяет быстрее написать "какой-то" код, но чтобы писать качественный и идеоматичный код, приходится вкатываться не сильно меньше Rust'а, ибо слишком много спрятанных граблей.
Что мне понравилось в Go - это скорре платформа, а не язык. В меру шустрая и не прожорливая, удобно деплоится. Ну и вкусности вроде из-коробочных тестов/доков/fmt, хотя оно и до сих пор сыровато.
Так то я совсем ушёл в Rust из Go, и Rust для меня по всем пунктам лучше, чем Go, кроме, разве что, ещё сырой экосистемы для веб-бекендов.
#![feature(async_await, async_closure)]

// [dependencies]
// tokio = "0.1.19"
// futures-preview = { version = "0.3.0-alpha.17", features = ["compat"] }

use futures::prelude::*;

pub type Handler<A> = dyn FnMut(Context<A>) + Send + 'static;

pub trait Address {}
impl<T> Address for T {}

pub struct Router<A> {
route: Option<Box<Handler<A>>>,
}

pub struct Context<A>(A);
pub type Caller<A> = Context<A>;


#[derive(Clone)]
pub struct Driver;

impl<A> Router<A>
where
A: Address,
{
fn set_sync_boxed<F>(&mut self, handler: Box<F>)
where
F: FnMut(Context<A>) + Send + 'static,
{
self.route = Some(handler);
}
pub fn set_boxed<F, T>(&mut self, mut handler: Box<F>)
where
F: (FnMut(Context<A>) -> T) + Send + 'static,
T: std::future::Future<Output = ()> + Send + 'static,
{
let handler = move |ctx| {
let fut = handler(ctx).unit_error().boxed().compat();
tokio::spawn(fut);
};
self.set_sync_boxed(Box::new(handler))
}
}

pub async fn info<A>(_ctx: Context<A>, _driver: Driver)
where
A: Address + 'static
{
unimplemented!()
}

#[cfg(test)]
mod tests {
use crate::*;
#[test]
fn it_works() {

let router: Router<u8> = Router {route: None};

let driver_inner = Driver{};
let handler = async move |ctx| {
info(ctx, driver_inner.clone()).await;
};
let handler = Box::new(handler);
router.set_boxed(handler);

assert_eq!(2 + 2, 4);
}
}
Возвращаясь к теме, что в расте запрещена рекурсия async-функций. Написал простейший web-scrapper на космическом языке dart :)) - выкачивает ссылки до определенной глубины, отсекая дубли, и замеряя время. И рекурсия асинхронной функции тут работает влет, а ведь dart умеет компилять в машинный код, то есть такое возможно в принципе сделать - стейтмашину с динамическим стеком, жду когда растишка до такого дорастет !
https://gist.github.com/epishman/703006571d273532619096412165a7bf
Channel name was changed to «Selected on Rust & Haskell & etc»
Channel name was changed to «Selected stuff on Rust & Haskell & etc»
Конвертация замыкания к FnMut

fn check(_: impl FnMut()) {}
fn main() {
let f = || {};
check(f);
}
Forwarded from Nikita Melkozerov
В линухе уже все есть:
/usr/bin/numactl -m 0 -N 0 ./hello-world