9 ms·
Story 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
by cletus 4y ago
Story 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