Hacker Newsnew | past | comments | ask | show | jobs | submit | J_Shelby_J's commentslogin

Depends on if you can fund a defense all the way to the Supreme Court.

Complexity of Rust is just codifying existing complexity.

I've been working on Rust bindings for a C SDK recently, and the Rust wrapper code was far more complex than the C code it wrapped. I ended up ceding and getting reasonable wrappers by limiting how it can be used, instead of moddeling the C API's full capabilities. There are certainly sound, reasonable models of memory ownership that are difficult or impossible to express with Rust's ownership model.

Sure, a different model that was easy to model would have been picked if we were initially using Rust, but we were not, and the existing model in C is what we need to wrap. Also, a more Rust-friendly model would have incured higher memory costs.


I totally hear you about C friendly APIs not making sense in rust. GTK struggles with this - I tried to make a native UI in rust a few months ago using gtk and it was horrible.

> Also, a more Rust-friendly model would have incured higher memory costs.

Can you give some details? This hasn’t been my experience.

I find in general rust’s ownership model pushes me toward designs where all my structs are in a strict tree, which is very efficient in memory since everything is packed in memory. In comparison, most C++ APIs I’ve used make a nest of objects with pointers going everywhere. And this style is less memory efficient, and less performant because of page faults.

C has access to a couple tricks safe rust is missing. But on the flip side, C’s lack of generics means lots of programs roll their own hash tables, array lists and various other tools. And they’re often either dynamically typed (and horribly inefficient as a result) or they do macro tricks with type parameters - and that’s ugly as sin. A lack of generics and monomorphization means C programs usually have slightly smaller binaries. But they often don’t run as fast. That’s often a bad trade on modern computers.


The code is written in an embedded style, i.e. no dynamic memory allocation or thread creation/deletion after program initialization. It's also prioritizing reducing memory usage over performance since we are targeting memory constrained devices (and our performance target is 10 tps and we have like 100k tps). Thus we'd use trait objects over monomorphization. Dynamic collections are also off the table unless backed by a fixed-size arena on the stack or static mem.

We heavily use arenas. We also have runtime-typed objects used to represent dynamically typed data like that obtained from JSON/Yaml or over IPC. If we were to be more friendly to modeling in Rust, we'd likely require that all memory reachable from an object node be in the same arena, disallowing common patterns like having list/map's arrays in one arena and having keys/strings in another or in static mem (this allows reusing other buffers without forcing copying all the data, so backing arrays can be smaller).


You said above:

> Also, a more Rust-friendly model would have incured higher memory costs.

I'm not sure how modelling everything in a rust borrow checker friendly way would change anything here? Everything you're talking about doing in C could be done more or less exactly the same in rust.

Arenas are slightly inconvenient in rust because the standard collection types bake in the assumption that they're working with the global system allocator. But there's plenty of high quality arena crates in rust which ship their own replacements for Vec / HashMap / etc.

It also sounds like you'd need to write or adapt your own JSON parser. But it sounds like you might be writing part of your own JSON / Yaml parser in C anyway.


Arenas aren't the issue. Its objects with mixed lifetimes and mutability. I cant easily model the lifetimes of objects when there are cases like an instance where buffer memory reachable from the object has a different lifetime than maps/lists. Also these objects could be transively shared or mutable. In order to make a Rust friendly model, I'd have the tree be all shared or all mutable, and have all reachable memory have the same lifetime. This would often mean allocating the full tree into one arena. That is where the overhead comes from. Each arena would need enough memory to store the entire object; currently they can be smaller since they often only need to hold parts of objects, not the entire thing.

This is ultimately a good example of how to use Rust. You express as much of the API as you can safely, and the rest is unsafe. APIs that can't be safely modelled can still be exposed to Rust & marked unsafe, if they're needed

That works for functions. For datatypes that are used throughout the API, it does not work so well.

Wouldn't a data type with no safe method of construction satisfy that? You can only get one by calling an unsafe function & satisfying its constraints.

That would be possible but also make its usage unergonomic and not the experience customers are expecting when requesting a Rust API.

Which SDK? I've only written Rust FFI to pretty basic C APIs. I'm curious to get a sense of the limitations on something more complex

The real reason single family housing ownership is the only real option is that society effectively pays people to own; appreciation out weighs all costs of ownership so in the end it’s free or even an investment.

But if it was truly a free market and supply met demand owning housing would be a depreciating asset and renting would be cheaper.

Land ownership is a cultural construct. Their is no natural state.


I use rust. The compiler is my agent.

Or to quote Rick and Morty, “that’s just rust with extra steps!”


On a related note, I've always regarded Python as the best IDE for writing C. :)

Replace memory with one of the dozen common issues the Rust compiler does nothing for like deadlocks.

Well, the case would still stand, wouldn't it? Unless C is free of these dozen common issues.

Wow that’s amazing. The partial equality implementation is really surprising.

One question about avoiding boolean parameters, I’ve just been using structs wrapping bools. But you can’t treat them like bools… you have to index into them like wrapper.0.

Is there a way to treat the enum style replacement for bools like normal bools, or is just done with matches! Or match statements?

It’s probably not too important but if we could treat them like normal bools it’d feel nicer.


I almost always prefer enums and matches! vs bool parameters. Another way is to implement a Trait that you find useful that encapsulates the logic. And don't forget you can do impl <Enum> {} blocks to add useful functions that execute regardless of which member of the enum you got.

    enum MyType{
    
    ...
    
    }

    impl MyType{
        pub fn is_useable_in_this_way(&self) -> bool{
            // possibly ...
            match self {...}
        }
    }
and later:

    pub fn use_in_that_way(e: MyType) {
        if e.is_useable_in_this_way() {...}
    }
Or if you hate all that there's always:

    if let MyType::Member(x) = e {
        ...
    }

If let is probably the closest to a regular bool.

For ints you can implement the deref trait on structs. So you can treat YourType(u64) as a u64 without destructing. I couldn’t figure out a way to do that with YouType(bool).


I think you can do something like impl defref but not sure that's a good idea hah. Maybe it's a different trait I'm thinking of

I wonder what the extremely rich do to get a car that isn’t a security risk? I’ve heard you can throw money at high end car dealerships to disable spying, but I wonder what the internal process is.

It's easier than that, you can remove the cellular modem. Dealers won't generally accept to make this mod, but any independent shop should be able to. There are also plenty of videos on YT to DIY.

I some months back called every independent EV mechanic I could find a listing for in my state to see if they would help me disable the cellular modem of any of the models I was interested in buying, and they mostly told me either that they couldn't or wouldn't. One of the more polite shops I got in touch with explained that many models don't have a separate board that can be disabled anymore, or otherwise have more things on the board that need to be talking on the CAN bus for other, actually important parts of the car to function. As such, I still have my old car.

Since then, I've learned about the 50ohm dummy antennas you can buy. I might try that if my car dies before an AWD/4WD Slate truck becomes an option, and also if my living situation can accommodate charging.


As far as I know, all modern Toyotas have discrete DCMs (data communication modules) that can be physically unplugged with limited side effects. The side effects are loss a speaker and hands-free microphone, but they be restored by means of a bypass harness. Simply unplugging the antennas does not seem to be enough in areas with good cellular coverage. I have seen the dummy load approach discussed on car forums but have no experience with it.

This will probably be a thing, but it's not clear that folks are cognizant of the risks yet.

I haven't heard this. Do you have any examples?

exactly. you specify types for function parameters and structs and let the language do it's thing. it's a bit of a niche to specify a type within a function...

There is a reason the multiple methods detailed above exist. Mostly for random iterator syntax. Such as summing an array or calling collect on an iterator. Most Rust devs probably don't use all of these syntax in a single year or maybe even their careers.


Do these print statements print the same thing?

    let i = 1;
    let j = 1;
    print!("i: {:?}\n", !i);
    print!("j: {:?}\n", !j);

    let v = vec![1, 2, 3];
    v[i];
There are definitely times you want to specify a type.


> There are definitely times you want to specify a type.

So I'm coming from basically obly TypeScript type system experience but that seems completely ok to me. There are times I make my TS uglier to make it less ambiguous and times I make it more ambiguous to make it more readable. It's unreasonable imo that such a system could universally land on the most readable format even if we could all agree what's most readable. Instead, some cases are going to be tradeoffs so that the more common cases can flow unimpeded.


The Rust example I showed changes behavior when you declare the types. It's not just a readability or bug catching thing.


I can't believe that a flexible powerful syntax is considered limiting or confusing by some people. There is way more confusing edge-case syntax keywords in C++ that are huge foot-guns.


Larger capacity is usually slower though. The fastest ram is typically 16 or 32 capacity.

The OP is talking about a specific niche of boosting single thread performance. It’s common with gaming pcs since most games are single thread bottlenecked. 5% difference may seem small, but people are spending hundreds or thousands for less gains… so buying the fastest ram can make sense there.


What is the best single thread performance possible right now? With over locked fast ram.


And Dyson has legal liability if they catch fire and a name brand to uphold if they don’t meet advertised runtimes. Amazon does not.

If you want a new battery for your Dyson, buy a tool battery adapter from Amazon and buy the tool battery from your local hardware store. Same price or less and you get insane run time + a new tool battery.


> buy a tool battery adapter

This x100. The Dyson batteries are expensive and die quickly (someone mentioned their experience mitigating the failure time by waiting to put the vacuum back on the charger until after it has cooled off). Getting a Milwaukee adapter for my Dysons has worked out really well. Runtime is much better, and I have one less custom battery size to deal with in my house.


Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: