9 ms·
Even though it'd be a while before this really affects the Chrome codebase, it's a real testament to how well Rust nails the safe-but-low-level niche. Google do
by riwsky 4y ago
Even though it'd be a while before this really affects the Chrome codebase, it's a real testament to how well Rust nails the safe-but-low-level niche. Google does not lack resources to tool (or staff!) a C++ codebase correctly, nor does it lack resources to build languages[1] targeting these specific problems; that they'd consider Rust isn't just because "it's there".
[1] https://github.com/google/wuffs https://github.com/google/wuffs
- cletus 4y agoStory time. I worked at Google years ago and there was a presentation once done on some optimizations done on Chrome performance. This is probably 10 years ago now. So C++ has std::string of course. C libraries however use "const char ", which has lots of problems. The C++ designers allowed you to avoid friction here by allowing you to pass a std::string to a function expending a const char . Technically, this is an operator method. It was discovered that the Omnibar in Chrome went through many layers of translations between std::string and const char *, back and forth, such that there were approximately 25,000 string copies per keypress in the Omnibar. So my point is that even with a ton of resources writing good, efficient and performant C++ is still nontrivial. And that's really the point of Rust (well, one of them).
- steveklabnik 4y agoHN comments on this story: https://news.ycombinator.com/item?id=8704318 https://news.ycombinator.com/item?id=8704318
- fractalb 4y agoIf all the dependent C libraries are replaced with C++ versions, then the no.of translations will become zero?
- woodruffw 4y agoNominally, yes. But conversions between C strings and `std::string` are just a small corner of the problem: C++ makes it very easy to accidentally call copying constructors and perform nontrivial copies when doing e.g. implicit argument conversion.
- jeffbee 4y agoYep, another serious performance problem (also at google, not in chromium) was caused by inaccurate declaration of lambda arguments in an STL algorithm call … ie std::something(begin, end, [](std::pair<foo, bar> foobar) -> bool {}). The actual type (iterating over an unordered map, I believe) would have been const foo, but the compiler correctly concluded it could implicitly create a pair of foo,bar by copy from pair of const foo,bar. These were the days before such arguments could be declared “auto” which would have avoided the problem. You have to think very very carefully about every line and character in C++ to figure out what it’s doing. Sometimes the easiest way to review it is to compile it and read the assembly.
- zaarn 4y agoConversions that create copies are always explicit in Rust (unless it's a copy type, which strings aren't). Conversion between the string types is at minimum taking the borrow of it and then taking a copy of the borrow is once again explicit. You can also cheaply use a CoW wrapper to get a no-copy string passed around into plenty of places. The point is, with rust you have more options to enforce no-copy through the type system.
- imron 4y ago> The C++ designers allowed you to avoid friction here by allowing you to pass a std::string to a function expending a const char . Technically, this is an operator method. It's the other way round. You can pass a const char* to a function expecting a std::string. Passing a std::string to a function expecting const char* will generate a compile error. You need to call c_str() on the std::string if you want to pass it as a parameter to a function expecting a const char*.
- gary_0 4y agoI'm not sure if this is what OP was referring to, but in the ancient past before the STL was fully standardized, some implementations had an `operator const char*` in std::string to allow implicit conversions.
- imron 4y agoPerhaps, but in the in the ancient past before STL was standardized, Chrome didn't exist. 10 years ago (when the parent mentioned they were still at Google) c++11 was already out.
- southerntofu 4y agoTen years ago was 2012. C++11 came out in 2011. Do you believe a big codebase like Chrome would be converted to C++11 less than one year after the spec was published? I find that unlikely but i never worked on such a big codebase so i wouldn't know.
- CJefferson 4y agoThe STL was mostly standardised in C++98, 1998. There were additions in C++03 and C++11, but nothing like removing this type of overload. Long running systems were still using pre-standardisation libraries for string up to 2012 however, so you may well have come across such projects.
- 4y ago
- mseepgood 4y agoHow would Rust help here? Isn't it famous for having too many string types?
- _nalply 4y agoIt's a complicated but well-thought out system which tends to avoid copies by making them explicit in the source code and preferring taking references or slices which are cheap operations. The string slice for example is an Unicode-capable view into bytes of the string (immutably pre-compiled static bytes in the binary, bytes of fixed length on the stack or heap-allocated). The aliasing rules are enforced by the compiler, so it is safe to throw around pointers and sizes and not to worry about buffer overflows, as long as it compiles.
- cowmoo728 4y agoIn C++ when I see `DoX(y)` I have to worry every time about temporary lifetimes, copy vs move operator, and a bunch of other things that are easy to miss during code review. It is so easy to accidentally copy large strings around many times in a performance critical loop. Rust makes all of that easier to see during code review. It is very explicit about these things. I'm a Google employee working on chromium and chromeOS and have been asking internally about rust support for over a year now, so it's exciting that it's making progress.
- imron 4y agoIt'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 have a &str (because you don't need to own the memory) and you pass it to any function that takes a String (or even the unidiomatic &String), then you will get a compile error. There won't be any implicit conversion of types and therefore no implicit allocation. If you really want to pass it, you need to explicitly convert it, making the cost of the allocation explicit. Rust's "too many strings" model says "there are many different ways in which you can use string-like objects, each with their own performance tradeoffs. Know which one you want to use in your code or I won't compile".
- secondcoming 4y agoThat’s just poor software. A poor Rust dev would be one who clones everything.
- seritools 4y ago`.clone()` is visible right in your code, though, unlike the implicit conversion/constructor magic.
- sseagull 4y agoBut you could write a C++ class with a manual .copy() method and a deleted copy constructor (and other conversion constructors not implemented). Doing that seems a bit easier than integrating a whole new language into your project (although I know Rust would have other benefits).
- TheCoelacanth 4y agoYou could do that if you are the author of std::string. Unfortunately, very few of us are.
- blub 4y agoBased on the code changes made at that time, it seemed that Chrome developers didn’t know how to write performant C++ code. Those were not difficult to understand C++ features either, but basic ones which were very well known by then. I remember reading Bulka & Mayhew’s Efficient C++ (published in 2000) which mentioned the importance of avoiding copies, calling reserve and many other techniques. So your point is wrong. Not copying strings all over the place, calling reserve, not creating temporary containers are junior-level C++ skills.
- ncmncm 4y agoYes. In two words, Google programmers are, as a rule, vastly overrated. They can maybe rope in 100,000 cores on one query, but nothing in their recruiting selects for good coding habits. Anybody coding C++ in this day'n'age and getting use-after faults needs to go to the back of the line. They will certainly succeed in writing new Rust code that is as bad as their old C++ code. (Note: deadlocks are officially "safe".) Recently Google made a big push to change the std::string constructor from a null char* to yield the empty string, instead of honestly segfaulting. That failed. They had a half-baked (and hellish, for users) async/await design they tried to put up as worth delaying the whole feature into 2023. That failed.
- pornel 4y agoSo where are those mythical "good C++ programmers"? I keep hearing that if only you find them, your C++ will be secure. But so far nobody has found them. Not Google, not Microsoft, not Mozilla. Rust succeeds, because it does not rely on programmers writing bug-free code. Bad Rust code is not as dangerous as bad C++ code. BTW: deadlocks are not exploitable for RCE, and are quite easy to debug compared to data races and heap sprays.
- ncmncm 4y agoThere is a very great deal of good C++ online. Google and Microsoft are handicapped by their need to hire in huge numbers, and must take who they can get.
- 4y ago
- Gigachad 4y agoFor me, the fact that the Linux project has decided that Rust will be included in the kernel was the point Rust has become a success. It's pretty clear at this point that Rust will be around for decades and start to replace the well established C space.
- flohofwoe 4y ago> the Linux project has decided that Rust will be included in the kernel Isn't this a bit oversimplified? IIRC the Rust support was only started as an option for writing device drivers in Rust, not actual kernel code, and even this relatively simple use case looks like a herculean effort which required changes to feed back into Rust - which is a good thing of course, but currently it looks like the Rust ecosystem benefits more from that project than the Linux ecosystem ;)
- tialaramex 4y agoFirstly yes, not all Linux targets are supported Rust targets, as a result if you were to rewrite Linux memory management code in Rust you can't ship that without breaking some Linux platforms. Over time it is expected that: Linux will stop caring about some very, very old targets; Rust will gain support for some more targets (especially those that aren't very, very old) and so this issue goes away. Meanwhile drivers cannot run on all targets so them being in Rust doesn't change whether your target can run Linux. Rust for Linux was driven by existing Linux developers. So they obviously think that's great news for Linux not just for Rust. One reason is: Nobody else was delivering a viable way forward. If there were ten of these safe low-level languages and by doing nothing Linux could be sure one would pick "Make ourselves suitable for Linux" as its goal then they could just sit back. Instead Rust is the only game in town, so it's either adjust Rust [ e.g. Rust for Linux alloc crate doesn't have the concatenating + operator on String like your userspace Rust does because that's the sort of thing which makes Linus angry ] or risk not having any safe path forward for the foreseeable future. And yes, ultimately whether Rust for Linux goes into the Linus tree at some point is always ultimately a decision for Linus Torvalds. It's just that he made friendly noises about it, and there are people putting the work in, so it's like for dozens of other prospective Linux features, we can assume it will land but we shouldn't assume when.