HNHacker News
TopNewBestAskShowJobs

ibraheemdev

4,933 karma · joined September 11, 2020

Software developer interested in building fast, concurrent, and robust systems.

Contact ibraheem@ibraheem.ca.

submissionscomments
ibraheemdev··on Async Rust doesn't have to be hard
This works with runtime agnostic futures, but you can't do any I/O without requiring a specific runtime. reqwest for example doesn't use a generic block_on, it runs tokio behind the scenes.
ibraheemdev··on Rust Is Hard, Or: The Misery of Mainstream Programming
I would say that threads work _very well_ for concurrency in _most_ apps. Thread context switches have gotten much much cheaper over the years, and the idea that threads are heavyweight is very outdated.
ibraheemdev··on On Java/JVM: Loom and Thread Fairness
It definitely can work, but Rust's model is incredibly powerful, and can make it easy to model complex control flow. Certain patterns, such as cancellation, can get pretty hairy in Go, although this is a place where Rust has some work to do as well :).
ibraheemdev··on On Java/JVM: Loom and Thread Fairness
Rust makes it very easy to use plain old OS threads, which work very well for many, dare I say _most_ use cases. OS threads are a lot lighter and cheaper than many realize, and async has it's own hidden costs. In the cases that OS threads don't cut it, a general purpose async runtime isn't likely to either. Green threading libraries are also possible without language integration [0], and though they require custom I/O types they have a synchronous API, which makes generic abstractions easier. Now of course if you want the async coding model with all it's benefits (selection, cancellation), then there is really no escaping it, but it's certainly not the only option.
ibraheemdev··on Learning Rust – Day 4 – Understanding Modules
The most common confusion with this is that when importing library code from your binary, you use `crate_name::...` as opposed to `crate::...`, as they are separate. You also don't have to declare the lib.rs as a module from the binary, and generally all your `mod` statements will reside in your lib.rs
ibraheemdev··on Our Experience Porting the YJIT Ruby Compiler to Rust
The rewrite commit is here for anyone interested: https://github.com/ruby/ruby/pull/5826
ibraheemdev··on Go's Concurrency Examples in Java 19
> There is no way for your operating system to know exactly how much stack space a thread will need so it allocates an amount on the order of around a megabyte. You only have around a bakers dozen gigabytes of RAM, so you can only make give or take 10,000 threads.

That's not true at all. The megabyte(s) of stack space is virtual, spawning a thread only requires a few kilobytes of memory initially, and is a lot cheaper than many realize.

ibraheemdev··on Speedsolving Rubik's Cube: 8355 Method
You can follow 2-look OLL/PLL with just a handful of algorithms.
ibraheemdev··on Hello V-Lang
The article seems to have been written by:

> a 15 year old student who likes to code and blog

for some perspective :)

ibraheemdev··on Is Rust Web Yet?
You can unsafe to get around the borrow checker, just not directly; you have to go through raw pointers.
ibraheemdev··on Is Rust Web Yet?
You can usually use pattern matching to get around a check followed by an unwrap. I would rewrite your example as:

    if let [first, ..] = &some_vec {
        print!("{}", first);
        // .. more code
    }
ibraheemdev··on Is Rust Web Yet?
If you look at the techempower submission source code you'll quickly see why: https://github.com/TechEmpower/FrameworkBenchmarks/blob/mast....
ibraheemdev··on Show HN: Fri – distraction-free writing in the terminal
I use Vim + https://github.com/junegunn/goyo.vim.
ibraheemdev··on Ask HN: Codebases with great, easy to read code?
A lot of the Java concurrency primitives written by Doug Lea and co. are great reads, and very well commented. See the source of `ConcurrentHashMap` for example: https://github.com/openjdk/jdk/blob/master/src/java.base/sha...
ibraheemdev··on Structured Concurrency
And possible related to the recent post of one of his projects, libmill: https://news.ycombinator.com/item?id=30699829, where libdill [0], "Structured Concurrency for C" was also mentioned.

[0]: http://libdill.org/

ibraheemdev··on Arkenfox: Firefox privacy, security and anti-tracking user.js template
For some context, there was discussion about Arkenfox over at the LibreWolf post: https://news.ycombinator.com/item?id=30722884
ibraheemdev··on libmill - Go-style concurrency in C
The follow up to this library was libdill, the library that I believe originally introduced structured concurrency: http://libdill.org/structured-concurrency.html
ibraheemdev··on Request Coalescing in Async Rust
That's a good overview similar to my experience.

> those are pointless for an internal backend with at most 10 concurrent connections

I'm also arguing that the benefit of async over threads at 10 _thousand_ concurrent connections is still unclear. Yes memory usage will be less, but memory is cheap. Context switching overhead may be less, but a lot of it is still there because of readiness-based I/O. We don't see new, high-scale systems built on blocking I/O perhaps not because they can't be, but because async has become the norm, at the cost of _a lot_ of complexity.

ibraheemdev··on Request Coalescing in Async Rust
> One thing I didn't mention is that epoll isn't even state of the art: there's a lot of work going on around io-uring and thread-per-core runtimes nowadays, which I'm following rather closely because again, at my day job it does matter!

io-uring is definitely a game changer, but it isn't async specific!

ibraheemdev··on Request Coalescing in Async Rust
> Which is all well and good, until we start hitting some limits. Like, maybe we have SO MANY CONNECTIONS that we run out of memory, because each of these threads has its own stack, and that's not free. It's not a lot, but a lot of "not a lot" quickly becomes a lot, as we all learn sooner or later.

I understand this was more of a side point as an introduction, but it's a very quick dismissal of blocking I/O that I've been seeing a lot. Modern threads + blocking I/O is much more performant than most people realize, often yielding better throughput than async due to reduced syscalls and other factors. Async is important when you are in an extremely latency constrained environment and/or need to prioritize tasks, but in other places, not so much. How much does increased stack memory usage really matter to a real server?

ibraheemdev··on Request Coalescing in Async Rust
> There was weird split where Hyper was the de facto http library, but the best web framework was actix-web which wasn't based on hyper.

actix-web, like hyper, is built on tokio, so I'm not sure why you see this as a weird split. The underlying HTTP server is not something you generally interact with. actix-web even _uses_ hyper (the h2 crate) for HTTP2.

ibraheemdev··on Request Coalescing in Async Rust
A lot of the difference likely comes from the fact that hyper implements HTTP keep-alive, meaning that multiple requests can be handled on the same connection, vs. having to create and terminate a conbection for every individual request.
ibraheemdev··on Announcing Actix Web v4.0
Actix-Web actually differentiates itself from most other Rust servers in that it runs multiple per-thread runtimes as opposed to a single work-stealing runtime. This probably doesn't matter to most, but if you really care about latency, it might be a factor to consider.
ibraheemdev··on What Is Rust's Hole Purpose?
For some context, this was written by Felix Klock, a lead of the Rust compiler team: https://github.com/pnkfelix
ibraheemdev··on Crafting a Lox Interpreter in Rust, Part 1
One cool pattern for tokens is a T! macro:

   macro_rules! T {
        (+) => { Token::Add },
        (-) => { Token::Sub },
        // ...
   }
This is really nice because it lets you match against tokens with `T![+]` instead of `Token::Add`.
ibraheemdev··on What I'd like to see in Go 2.0
The type sets proposal for Go has already been accepted as part of the generics proposal [0]:

    type SignedInteger interface {
        ~int | ~int8 | ~int16 | ~int32 | ~int64
    }
Interfaces that contain type sets are only allowed to be used in generic constraints. However, a future extension might permit the use of type sets in regular interface types:

> We have proposed that constraints can embed some additional elements. With this proposal, any interface type that embeds anything other than an interface type can only be used as a constraint or as an embedded element in another constraint. A natural next step would be to permit using interface types that embed any type, or that embed these new elements, as an ordinary type, not just as a constraint.

> We are not proposing that today. But the rules for type sets and methods set above describe how they would behave. Any type that is an element of the type set could be assigned to such an interface type. A value of such an interface type would permit calling any member of the corresponding method set.

> This would permit a version of what other languages call sum types or union types. It would be a Go interface type to which only specific types could be assigned. Such an interface type could still take the value nil, of course, so it would not be quite the same as a typical sum type.

> In any case, this is something to consider in a future proposal, not this one.

This along with exhaustive type switches would bring Go something close to the sum types of Rust and Swift.

[0]: https://github.com/golang/go/issues/45346

ibraheemdev··on Go Replaces Interface{} with 'Any'
What about it?
ibraheemdev··on Some thoughts on writing
I believe if you resubmit with "How" re-added, it keeps it.
ibraheemdev··on Monoio – A thread-per-core Rust async runtime with io_uring
actix-rt is a wrapper around tokio's single threaded runtime, and (optionally) tokio-uring.
ibraheemdev··on Improving GitHub Code Search
https://grep.app/ is a great alternative to github's current search engine.
← PreviousPage 2 of 17Next →