Live data from Hacker News

Experimenting with Rust in Chromium

chromium.googlesource.com

91–100 of 115 posts

Re: Experimenting with Rust in Chromium

#91
post #88

Earlier quoted context omitted.

Copying short strings does not necessarily involve an allocation in implementations using short string optimization. Shooting down the cache line in a remote CPU that happens to have used a frequently-used string recently is absurdly expensive by comparison.

The COW and short string optimizations are not mutually exclusive. If we assume short string optimization is implemented both before and after, then we are back to comparing the atomic increment to allocation. And different allocation approaches can make the cost of heap allocation differ quite substantially. I'd fully expect that some allocation approaches are cheaper than the cache line invalidation from atomic inc…

You have accurately described the GNU CoW string :-)

My impression through the fog of history is that what happened was a really clever GNU person with little foresight and no access to an SMP system implemented std::string with CoW. Its performance in practice was so poor that the standard committee intentionally changed the standard to make it an illegal implementation, thereby eradicating the GNU CoW string. There was no higher principled logic.

Re: Experimenting with Rust in Chromium

#92
post #91

Earlier quoted context omitted.

The COW and short string optimizations are not mutually exclusive. If we assume short string optimization is implemented both before and after, then we are back to comparing the atomic increment to allocation. And different allocation approaches can make the cost of heap allocation differ quite substantially. I'd fully expect that some allocation approaches are cheaper than the cache line invalidation from atomic inc…

You have accurately described the GNU CoW string :-) My impression through the fog of history is that what happened was a really clever GNU person with little foresight and no access to an SMP system implemented std::string with CoW. Its performance in practice was so poor that the standard committee intentionally changed the standard to make it an illegal implementation, thereby eradicating the GNU CoW string. There…

Yet more recent benchmarks show that there are pretty important use cases where CoW string can be faster:

https://blogs.msmvps.com/gdicanio/2016/07/09/is-copy-on-writ...

https://oribenshir.github.io/afternoon_rusting/blog/copy-on-...

Also, the point of that was to improve multithreading of string: I think this very idea is problematic. I've written at this point hundreds of thousands of line of C++, and the number of times where strings are really, by design, supposed to be shared across threads is honestly counted on the fingers of one hand, just like e.g. justification for using Arc over Rc in rust. 99% of string handling is done as some GUI work on the main thread or as part of some task processing done in some network thread, which stays in that thread.

Re: Experimenting with Rust in Chromium

#93

Earlier quoted context omitted.

> the ancient past before the STL was fully standardized Specifically the "ancient past" here is prior to C++ 11 when C++ decided now it wanted to actually define how its string type works because C++ 98 and C++ 03 strings are both even more dangerous than most things are in C++ and had to be put out of their misery.

> because C++ 98 and C++ 03 strings are both even more dangerous ... how so ? they were just CoW which is actually I think the better choice most of the time... now there are copies all over the place

The C++ API lets you take references into the string. These, understandably, are lightweight, no C++ programmer would expect a reference into the sixth character of a string s[5] to be expensive to make or carry about, but they're mutable and as a result of being lightweight they are not reference counted...

So I've got the string "IR Baboon big star of cartoon" and I take references into it, which are cheap and then you use your C++ 98 copy constructor to get another string, which of course also says "IR Baboon big star of cartoon", when you took it -- and then I scrawl "I AM Weasel" on top of my string using my reference and now your string was changed because it was COW.

If you liked COW for this purpose Rust has std::borrow::Cow which is a smart pointer with similar flavour, Cow is a sum type that's either a thing you own T (and thus you could modify it) or it's a reference, perhaps &T (and thus you can't modify it) but which promises you could get an owned thing (e.g. for strings by deep-copying the string) if you need one. Methods that would be OK to call on the immutable reference (e.g. asking how many times an ASCII digit appears in the string) work on Cow and if you find you need to mutate it (maybe in a rare case) you can ask the Cow for the mutable version, if it already had the owned version you get that, if not it will make one for you.

Rust's traits kick in here, Cow requires T: ToOwned, which is a trait saying "I can make an immutable reference to T into a new thing T you own", obviously types you shouldn't do that to simply do not implement ToOwned and so you can't make a Cow of those types. The standard library provides in particular an implementation of ToOwned for &str which makes Strings from it.

Re: Experimenting with Rust in Chromium

#94
post #23

Earlier quoted context omitted.

It's the 'too many string types' that helps. With C++, if you have char*'s (because you don't need to own the memory) and you pass it to a function that takes a const std::string& (because it also doesn't want to own the memory), then there will still be an implicit conversion to a temporary std::string (involving an allocation) despite neither the caller or the callee needing to own any memory. With Rust, if you hav…

This discussion is making me wonder if windows-rs [1], the crate with official Rust bindings for all Windows APIs, is doing something that's not idiomatic Rust. Specifically, for any Windows API function that takes a UTF-16 string as a parameter, the signature for that parameter is something like "impl IntoParam ". The crate then implements that trait for String and &str, so you can pass a normal Rust UTF-8 string (e…

Well that will be necessary until windows gets UTF-8 APIs. Probably not soon. Until then there are various optimizations you can do, like caching the UTF-16 conversion alongside the UTF-8 string (good for calling OS APIs frequently with with long-lived strings), allocating temporary UTF-16 conversions on the stack (good for infrequent calls with strings up to a certain size), or storing raw UTF-16 strings as opaque bytes in Rust memory (good for providing strings back to the OS that you got from the OS).

You should try to avoid calling OS APIs in general and cache the results as much as possible. Who knows what the performance characteristics are of an API that has to serve 7 layers of historical OSes simultaneously. Unless you're directly interfacing with the kernel you shouldn't expect much. Omnibar-like layered calls between your app and the OS are a worst-case scenario regardless of conversions.

Re: Experimenting with Rust in Chromium

#95
post #91

Earlier quoted context omitted.

You have accurately described the GNU CoW string :-) My impression through the fog of history is that what happened was a really clever GNU person with little foresight and no access to an SMP system implemented std::string with CoW. Its performance in practice was so poor that the standard committee intentionally changed the standard to make it an illegal implementation, thereby eradicating the GNU CoW string. There…

Yet more recent benchmarks show that there are pretty important use cases where CoW string can be faster: https://blogs.msmvps.com/gdicanio/2016/07/09/is-copy-on-writ... https://oribenshir.github.io/afternoon_rusting/blog/copy-on-... Also, the point of that was to improve multithreading of string: I think this very idea is problematic. I've written at this point hundreds of thousands of line of C++, and the number of…

Clearly there's a frontier where the cost situation begins to favor the CoW approach, and I think authors should consciously choose whether they want a CoW string or not based on their use-case, but that goes against the idea of std::string as a jack-of-all-trades. Personally I don't really like std::string as a concept. It overlaps with too many other concepts. It is just vector or std::unique_ptr with SSO? The latter is nice in cases where you want std::string to adopt or release existing memory. Or do you want something like absl::Cord, which is like the old GNU CoW string but with even more stunts under the hood?

Re: Experimenting with Rust in Chromium

#96
post #58

Earlier quoted context omitted.

Yes, I believe literally every single 'in the wild' exploit has abused memory unsafety, as well as hundreds of vulnerabilities every year.

That's strange... if they'd written the code in a memory safe language, say, Java... there wouldn't be any vulnerability? I don't know... I see plenty of vulnerabilities in the Java world, no memory unsafety needed.

Vulns exist in Java applications. Logic bugs can open all sorts of doors to exploitation. But empirically we observe that a huge portion of real vulnerabilities in applications written in C or C++ are memory errors. We've spent decades trying to get people to write C and C++ applications without these errors and utterly failed.

A browser written in a memory safe language won't be free from vulns but it will be free from a huge class of recurring and very serious vulns.

Re: Experimenting with Rust in Chromium

#97

Earlier quoted context omitted.

This discussion is making me wonder if windows-rs [1], the crate with official Rust bindings for all Windows APIs, is doing something that's not idiomatic Rust. Specifically, for any Windows API function that takes a UTF-16 string as a parameter, the signature for that parameter is something like "impl IntoParam ". The crate then implements that trait for String and &str, so you can pass a normal Rust UTF-8 string (e…

Well that will be necessary until windows gets UTF-8 APIs. Probably not soon. Until then there are various optimizations you can do, like caching the UTF-16 conversion alongside the UTF-8 string (good for calling OS APIs frequently with with long-lived strings), allocating temporary UTF-16 conversions on the stack (good for infrequent calls with strings up to a certain size), or storing raw UTF-16 strings as opaque b…

winapi does support UTF-8 on recent versions:

https://docs.microsoft.com/en-us/windows/apps/design/globali...

Re: Experimenting with Rust in Chromium

#98

Earlier quoted context omitted.

Well that will be necessary until windows gets UTF-8 APIs. Probably not soon. Until then there are various optimizations you can do, like caching the UTF-16 conversion alongside the UTF-8 string (good for calling OS APIs frequently with with long-lived strings), allocating temporary UTF-16 conversions on the stack (good for infrequent calls with strings up to a certain size), or storing raw UTF-16 strings as opaque b…

winapi does support UTF-8 on recent versions: https://docs.microsoft.com/en-us/windows/apps/design/globali...

Very interesting I wasn't aware. After glancing over that doc, it looks like they smuggle UTF-8 in through the -A variant windows APIs [1] by explicitly setting the CP_UTF8 codepage in an application manifest. I wonder if this actually uses UTF-8 internally to service the API call or if it just manually converts strings to wide form and calls the -W variant on the windows side instead of making you do it on the app side. If the latter it may be better to avoid this feature so you don't close the door on potential optimizations like I mentioned above.

[1]: Windows has two variants of many API calls with either -A or -W suffix, where the -A suffix is for strings formatted as 1-byte ASCII (or a specified codepage) and the -W suffix is for strings formatted as 2-byte UTF-16 (kinda). Example: DlgDirListA / DlgDirListW, https://docs.microsoft.com/en-us/windows/win32/api/winuser/n...

Re: Experimenting with Rust in Chromium

#99
post #58

Earlier quoted context omitted.

Yes, I believe literally every single 'in the wild' exploit has abused memory unsafety, as well as hundreds of vulnerabilities every year.

That's strange... if they'd written the code in a memory safe language, say, Java... there wouldn't be any vulnerability? I don't know... I see plenty of vulnerabilities in the Java world, no memory unsafety needed.

The question was if the exploits were due to memory safety. The answer is, yes, 100% of them are due to memory safety.

As for Java, quite a lot of the exploits against it (when it was a browser plugin) were in fact memory safety issues in the VM. But more recently what we see are serialization issues, which Rust also does not have.

Re: Experimenting with Rust in Chromium

#100

Earlier quoted context omitted.

Just to clarify, exploit generally refers to software that takes advantage of vulnerabilities, vulnerabilities are the flaws themselves. As in, one writes code to "exploit" a "vulnerability". 70% of all vulnerabilities reported to them are memory safety issues. To my knowledge, 100% of exploits against Chrome in the wild leverage memory unsafety.

How anyone can read a survey like this and still argue that the benefits of Rust (or any language with the ownership model) don't outweigh the risks / negative aspects is beyond me.

Most developers understand virtually nothing about security.
Post reply on HN