Live data from Hacker News

Std::string half of all allocations in the Chrome browser process

groups.google.com

101–110 of 170 posts

Re: Std::string half of all allocations in the Chrome browser process

#101

Earlier quoted context omitted.

Interestingly, with Rust, the borrow checker makes it statically safe to know when you can stack alloc.

You can also do it in a more limited set of cases in other languages using escape analysis. You can't provide it in all cases, but in a subset of cases you can show that the allocation never escapes a certain stack context, and therefore it's safe to stack-allocate. I believe the JVM does that in many cases.

> You can't provide it in all cases,

I'm curious how reliable it is. It seems simple, intuitively, but Java (the JVM?) seems to have a reputation of being sub-par in this respect. Maybe it has to do with knowing how the the variables that are sent to other methods are used; if it only has local knowledge (the method that the object is created in), then I guess it has to be pessimistic with regards to all objects that are used as a parameter in method calls in that method.

Re: Std::string half of all allocations in the Chrome browser process

#102
post #58
post #37

Earlier quoted context omitted.

"Lessons learned, their strings work" Except that they don't. Either they are 'complete' but massive and thus slow, or they start as 'array of byte' and then their designers spend 10 years implementing a more 'complete' string type that is still fast enough and end up as #1 anyway. Of course the C++ way where there is no string type that everyone uses sucks too, it's just that strings are almost impossible to get 'ri…

I think this bears trumpeting: strings are hard! It's easy to gloss over their issues via garbage collection and pervasive heap allocation, but once you're in a domain where you care about stack allocation and avoiding copies you start running into difficult tradeoffs (above and beyond even the question of string encoding, which is a different beast altogether). Speaking as a dynamic language programmer who's trying…

I wonder how cavalier people treat strings when they feel like "primitive values" in the language - like Java having the (+) operator for concatenation.

I don't agree with the view that "costly" (it's all relative, but anyway) operations should look "costly" (i.e., be a relative eyesore). But I don't doubt that it can affect one's mindset.

Re: Std::string half of all allocations in the Chrome browser process

#103
post #69
post #58

Earlier quoted context omitted.

I think this bears trumpeting: strings are hard! It's easy to gloss over their issues via garbage collection and pervasive heap allocation, but once you're in a domain where you care about stack allocation and avoiding copies you start running into difficult tradeoffs (above and beyond even the question of string encoding, which is a different beast altogether). Speaking as a dynamic language programmer who's trying…

If you care about performance use std::performant_but_tricky_string. 99% of code doesn't care about string-related performance, but needs string anyway.

If you care about performance at all, strings are going to slow you down in unexpected and counter-intuitive ways.

Far better if you pass around text data as binary buffers (with metadata describing encoding, please), and only convert those to strings once they are ready to be consumed by the user (which is typically not where performance bottlenecks show up anyways)

Re: Std::string half of all allocations in the Chrome browser process

#104
post #32

Earlier quoted context omitted.

It's called the short string optimization. It was used once but I am not sure if it is any more. C++11 move semantics may help a lot with string churning...

As others have mentioned some libraries do use it. It has tradeoffs though. In a "traditional" implementation sizeof(std::string)==sizeof(char * ) -- it keeps a pointer to the first byte of the text with the metadata (minimally: size and capacity) stored before it in memory. c_str() is just a "return p_;" and size() is something like "return reinterpret_cast (p_)[-1];" Now to add the short-string optimization you nee…

2. You can actually go up to 7 bytes as long as you're sure you get word-aligned pointers back from malloc (usually a good bet). Make the tag the last byte, indicate a short string by "tag_byte & 0x07 != 7", and then store the length as "7 - tag", reserving tag 7 for pointers. If it's a 7-byte string, then the tag byte itself will be 0, serving as the null terminator. If it's Whether these gymnastics are worth it is debatable. My intuition is that you lose more in bit-twiddling instructions on common operations than you gain by being able to store an extra byte in short strings, but I'd want to benchmark on real data before implementing.

Re: Std::string half of all allocations in the Chrome browser process

#105
post #97

Earlier quoted context omitted.

Hehe, ignorance truely is bliss I guess. Just ask yourself: what size is a char in Java? To unearth 90% of the problems with strings in any language, ask two things: first, what size is char? Any secondly, what is the length of a string? If you cannot talk about these things for an hour, you don't really understand how computers deal with strings.

Actually, no. 90% of the problems with strings in any language is somebody screwing up the character encoding, usually out of ignorance. The fact that every object in Java has some overhead and probably needs some padding for alignment is utterly irrelevant. But since you asked: - 8 bytes generic object overhead per String - 4 bytes for the char[] ref - 12 bytes for the char[] itself, if non-null, plus probably 4 byt…

> My customer's servers have usually 8Gb or RAM, 16Gb is becoming the norm.

Does the cache sizes not matter? Honest question.

Re: Std::string half of all allocations in the Chrome browser process

#106
post #4

I've worked on a project that used all of these: std::string, QString, OString, char*. All were required by a different library that we needed. This is why a good string type should be in core language.

The real language problem is that classes are closed -- you can't add your own methods to std::string (other than operators) As a C++ program grows it's more and more tempting to make your own private string class (either by inheriting from std::string, encapsulating it, or reimplementing it) that interacts more naturally with your program's other types. I've done this myself. Of course this works great until you nee…

[deleted]

Re: Std::string half of all allocations in the Chrome browser process

#107
25000 (!!) allocations are made for every keystroke in the Omnibox.

The Omnibox is no doubt far more complex than simple text box since entering characters into it can invoke things like network connections (for search suggestions), but 25k allocs is still a bit on the excessive side.

Strings are an interesting case in that in general they are of indeterminate (and variable) length, which makes them somewhat difficult to accommodate in computer memory which is finite and allocated in fixed-length pieces. Abstractions like std::string have been created to make it simpler and easier to perform operations like appending, resizing, copying, and concenating, but I think this is part of the problem: by making these operations so easy and simple for the programmer, they're more inclined to overuse them instead of asking questions like "do I really need to create a copy just to modify one character? do I really need to append to this string? how long can it be?" Essentially, the abstraction encourages ignorance of the real nature of the actual operations, leading to more inefficient code. It only helps the programmer to perform these tedious operations more easily, and doesn't help at all with the decision of whether such tedious operations should be needed at all, which I think is more important; the first question when designing shouldn't be "what abstractions should I use to do X?", but "do I really need to do X, or is there are simpler way that doesn't need to?" The most efficient way to do something is to not do it at all.

Contrast this with a language like C, in which string operations are (unless the programmer writes or uses a library) far more explicit, and the programmer can be more aware of what his/her code is actually doing. That's why I believe every programmer who has to deal with strings should have at one point been exposed to implementing a resizable string buffer and/or length-delimited string library, to see the real nature of the problem (including how to do length management correctly.) Without this basic, low-level understanding of how to use memory, the advantages of all the other fancy string abstractions won't make much sense either.

Re: Std::string half of all allocations in the Chrome browser process

#108
post #69

Earlier quoted context omitted.

If you care about performance use std::performant_but_tricky_string. 99% of code doesn't care about string-related performance, but needs string anyway.

If you care about performance at all , strings are going to slow you down in unexpected and counter-intuitive ways. Far better if you pass around text data as binary buffers (with metadata describing encoding, please), and only convert those to strings once they are ready to be consumed by the user (which is typically not where performance bottlenecks show up anyways)

If you care about performance a lot, it may well be that most of your critical paths are in numeric code, and strings are only used to read input and write output. So you should just use strings unless profiling shows problems there.

Re: Std::string half of all allocations in the Chrome browser process

#109
post #37

Earlier quoted context omitted.

"Lessons learned, their strings work" Except that they don't. Either they are 'complete' but massive and thus slow, or they start as 'array of byte' and then their designers spend 10 years implementing a more 'complete' string type that is still fast enough and end up as #1 anyway. Of course the C++ way where there is no string type that everyone uses sucks too, it's just that strings are almost impossible to get 'ri…

It boggles the mind how many different ways to represent Strings there are in C++, and String handling in general is the major reason I'll never touch it (or C) with a 10 feet pole. I'm interested to hear though how the String handling in Java is broken. This is everything I have to know: - String - CharSequence - char[] / Character[] - StringBuilder Done. Finito. Strings are immutable, the GC will clean up after me.…

Except that:

- In CJK languages, unicode codepoints can't be represented in 2 bytes. They take up 2 'char' objects; the first is a surrogate code point.

- In the presence of surrogates, charAt() and length() give wrong answers. Their indexes refer to the number of 'char' objects up through that point, not the number of Unicode codepoints. If there is a surrogate codepoint present anywhere before your index in the string, you will be off.

- To help get around this, the Java APIs added codePointAt and codePointBefore. These are still broken; the indexes are based off of chars, not codepoints.

- To get around this, we have codePointCount and offsetByCodePoint. Finally, these are semantically correct. However, they give up O(1) string indexing.

Did you know all of this? There's more, too, where calling CharSequence.subSequence causes a memory leak because you're pulling out a small portion (say, 10 bytes) of a large backing buffer (say, 1MB), and storing it in a persistent object prevents the GC from collecting the buffer, since a portion of its data is still live. This has caused real memory leaks in Google servers, enough that they had to educate the whole developer base about the pitfalls of it. But I figured I had enough to pick on with Java's broken Unicode handling to illustrate the grandparent's point: strings are hard. If you think you understand them, you're probably not aware of some of the trade-offs between performance, correctness, multilingual support, and developer APIs.

Re: Std::string half of all allocations in the Chrome browser process

#110
post #105

Earlier quoted context omitted.

Actually, no. 90% of the problems with strings in any language is somebody screwing up the character encoding, usually out of ignorance. The fact that every object in Java has some overhead and probably needs some padding for alignment is utterly irrelevant. But since you asked: - 8 bytes generic object overhead per String - 4 bytes for the char[] ref - 12 bytes for the char[] itself, if non-null, plus probably 4 byt…

> My customer's servers have usually 8Gb or RAM, 16Gb is becoming the norm. Does the cache sizes not matter? Honest question.

Thats not so easy to answer. It starts to matter a lot when you get into very high performance architectures (think disruptor, anything requiring lots of mechanical sympathy, highly contended memory access etc.), but usually you're waiting for the database or the network anyway.

Supposing you meant memory bloat compared to C, increased developer productivity is almost always more important. Things like memory access patterns can be important when you are interested in optimizing hot loops, but not generally.

Post reply on HN