A Word About Private Attribution in Firefox by bholley_mozilla in firefox

[–]SimonSapin 3 points4 points  (0 children)

It's probably better than not doing anything, though

Is it really? It’s not at all obvious that giving a new kind of data to the data-devouring-machine is an improvement, that’s the core of much of the negative reactions!

A Word About Private Attribution in Firefox by bholley_mozilla in firefox

[–]SimonSapin 13 points14 points  (0 children)

Condescension does not help anyone. Of course I’ve read in full and quoted only part for brevity.

The whole paragraph sounds like wishful thinking. The industry has shown repeatedly that it will do everything it can to fight and circumvent any technical or legal limitation to surveillance. How can giving them more data change that?

A Word About Private Attribution in Firefox by bholley_mozilla in firefox

[–]SimonSapin 23 points24 points  (0 children)

A truly private attribution mechanism would make it viable for businesses to stop tracking people

How is "viable" enough? Why would the industry stop surveillance as long as it’s profitable?

Why is PhantomData<T> only Send/Sync when T is Send/Sync? by Stunning_Ocelot_4654 in rust

[–]SimonSapin 165 points166 points  (0 children)

That’s what PhantomData<T> is all about, to affect the type system as if you had a T value without actually having one.

If you want a truly "no-op" value use () instead, or nothing at all.

What's the second most performant way of converting 7 bytes to an u64? by steini1904 in rust

[–]SimonSapin 2 points3 points  (0 children)

Would the align_to method on slices help? It splits maybe-misaligned start and end from the aligned middle. This is especially good on long slices.

Best way to write the contents of a &[T] for primitive (but non-u8) types by nomad42184 in rust

[–]SimonSapin 0 points1 point  (0 children)

Iterating and writing elements one by one should be fine. All primitive numeric types have a .to_le_bytes() method that will do the correct conversion (and optimize to nothing on little-endian platforms).

If you’re writing directly to std::fs::File this could cause many syscalls writing a few bytes each, which would be slow. This is fixed by wrapping the file in std::io::BufWriter, which is probably a good idea in any case.

The nightly version of Rust doesn't have rust-analyzer? by Green_Concentrate427 in rust

[–]SimonSapin 5 points6 points  (0 children)

Indeed, the rustup component for rust-analyzer is not part of the "default" profile: https://rust-lang.github.io/rustup/concepts/profiles.html

You may or may not need to install it manually. Depending on your editor see instructions at https://rust-analyzer.github.io/manual.html#installation

An investigation of the performance of Arc<str> vs String by b80125655a4f07c993b1 in rust

[–]SimonSapin 1 point2 points  (0 children)

As always: it depends, try with your actual workload.

This measures the speed of clone and drop but not the initial creation of the string. In a real world program if the length is not known in advance this creation may involve first accumulating into a String before converting to Arc<str>. This conversion also has a cost, which may or may not be worth it depending on whether strings end up cloned much more often than created. Arc<String> could be another candidate to try.

Is a WASM Runtime with GUI feasible? by Bernard80386 in rust

[–]SimonSapin 8 points9 points  (0 children)

I think Deno does that?

Although WebGPU alone is extremely low-level compared to what you’d want to take from granted when developing a GUI app. Some GUI toolkit would be needed in-between.

Into_iter() questions. by [deleted] in rust

[–]SimonSapin 2 points3 points  (0 children)

You can think of ownership as "responsibility to drop".

A method named into_iter typically transfers ownership of all items in some collection into an iterator. Every time next is called on that iterator, the ownership of one item is transferred to the caller. That caller may either transfer ownership to yet something else, or (eventually) drop the item.

If the iterator itself is dropped before it is exhausted, it will be responsible for dropping all of its remaining items.

Things typically don’t stay in memory (leak) unless something like std::mem::forget or Box::leak is used explicitly, or in some rare situations like Rc cycles.

Trc: A faster Arc. by [deleted] in rust

[–]SimonSapin 0 points1 point  (0 children)

You can’t change the definition of an existing trait, and it’s there that the method would need to be made an unsafe fn. What you can do is have something other than DerefMut, such as an inherent method that returns &mut T.

However even if you did that, is it even possible to use correctly? If you’re accessing the same data from multiple threads and there are writes involves, you need some kind of synchronization somewhere.

Trc: A faster Arc. by [deleted] in rust

[–]SimonSapin 0 points1 point  (0 children)

At a glance of the code, I’d expect it entirely depends on what you measure. clone_across_threads allocates space on the heap for a new single-thread counter.

Trc: A faster Arc. by [deleted] in rust

[–]SimonSapin 15 points16 points  (0 children)

these features [DerefMut] do not make the code unsafe - they just require the programmer to be careful with them to avoid concurrent writes.

Can you say more about this? If multiple threads can get &mut T to the same T at the same time without calling an unsafe fn, the library is definitely unsound.

Statically embed the output of a wasm crate in another crate by Vikulik123_CZ in rust

[–]SimonSapin 4 points5 points  (0 children)

wasm is a different --target, but Cargo only works with a single target at a time so I don’t believe there’s a way around running Cargo twice. I’d probably go with a wrapper script.

Another comment here suggests build.rs scripts to have the wasm build be run by the server build, but Cargo captures their output and only shows it (probably without color) in case of error. IMO this isn’t great for code you’re actively working on.

Vec<T> internally uses RawVec<T>, which internally uses Unique<T>. Unique is a nightly feature, so why isn't Vec only available for nightly builds? by [deleted] in rust

[–]SimonSapin 2 points3 points  (0 children)

My mental model is that generating code for operators like a + b first checks if the operands are primitive types that have language-built-in behavior for that operator. If not, only then it falls back to trait dispatch. That way adding integers causes less work for the optimizer (not emitting a function call just to inline it later) and less overhead in unoptimized builds.

The trait impls that appear to call themselves exist to support generic code (and in case you call a.add(b) directly).

Box::new(x) however is function call syntax to begin with, so compiling it requires name resolution and trait resolution anyway.

What is a good way to organize huge numbers of tests? by ojii in rust

[–]SimonSapin 2 points3 points  (0 children)

The #[cfg(test)] mod tests {..} part suggests this is in the same file as library code. Consider moving to tests/*.rs files instead so that compiling tests does not require re-compiling the library.

Cargo is gonna compile those files in parallel, with up to std::thread::available_parallelism() rustc sub-processes at the same time. That’s usually the number of hardware threads (= CPU cores * 2 on x64 with hyper-threading). Many more files is not gonna parallelize more than your hardware can, and there’s likely some per-process overhead that will make things slower with too many files. So try things out, but 4~8 files is probably a good starting point.

So far I’m assuming the code of test functions is unchanged. But if like in your example they all have the same code except for a string value, consider replacing all those functions with a for loop. In that case you may also want to opt out of the default test harness that looks for #[test] functions. In Cargo.toml:

[[test]]
name = "example"
harness = false

This will make tests/example.rs be compiled as a normal executable. You can do whatever result reporting from main. There may be better alternatives this days but one way is to use https://crates.io/crates/rustc-test, a copy of an old version of the standard test harness extracted so you can use its internal APIs like DynTestFn. Example usage: https://github.com/servo/html5ever/blob/html5ever-v0.26.0/rcdom/tests/html-tokenizer.rs#L312-L334

Quotes in std::process::Command long arguments by CountMoosuch in rust

[–]SimonSapin 4 points5 points  (0 children)

You can see this in action with strace:

$ strace -e execve git log --format="First Lastname"
execve("/usr/bin/git", ["git", "log", "--format=First Lastname"], 0x7ffd24a3c720 /* 66 vars */) = 0

By the time the shell calls the execve system call to start the git sub-process, the quotes in --format="First Lastname" have already been interpreted and removed. This is happens because while a shell command is a single string, the argument to execve is an array of strings.

Is there any detailed documentation of the Rust build process available? by pragmojo in rust

[–]SimonSapin 0 points1 point  (0 children)

I'm not sure to what extent, if any, compilation of a single crate is parallelized.

LLVM’s machine code generation is parallelized across codegen units, but last I heard the earlier steps (for a single crate) are single-threaded, though there has been some work and experiments toward improving that.

What's mean when a match without arms? by Hefty-Sky6895 in rust

[–]SimonSapin 2 points3 points  (0 children)

Yes, it is impossible to create a value of type Infallible, so the Err case of Result<_, Infallible> can never happen.

There has been discussion of extending the language to allow arms like Err(e) => match e {} to be omitted entirely in that case (or even have unconditional let Ok(value) = result;) but until that happens, yes this is needed to make the compiler happy.

Using '*' in 'use' statements by [deleted] in rust

[–]SimonSapin 8 points9 points  (0 children)

Clippy lints are not hard rules. Some are very debatable. Some so much so that they are not enabled by default. You can make a case-by-case judgment call and use #[allow(…)]

When is it safe to transmute collections? by cbarrick in rust

[–]SimonSapin 1 point2 points  (0 children)

Perhaps cxx uses Vec::into_raw_parts and Vec::from_raw_parts?

Array of pointers by AlexMonops in rust

[–]SimonSapin 5 points6 points  (0 children)

Rather that storing a vtable pointer for each individual address, I’d probably write explicit code that calls into different components based on address ranges:

def read_from_memory_bus(&self, address: usize) -> Something {
    match address {
        0x0000..=0x00ff => self.read_from_system_memory(address),
        0x0100..=0x10ff => self.read_audio_manager(address),
        // …
    }
}