Live data from Hacker News

Use string views instead of passing std:wstring by const&

giodicanio.com

51–55 of 55 posts

Re: Use string views instead of passing std:wstring by const&

#51
post #7

Earlier quoted context omitted.

C strings also allow you to do a 0 copy split by replacing all instances of the delimeter with null (although you need to keep track of the end-of-list seperatly).

You also need to own the buffer otherwise you’re corrupting someone else’s data, or straight up segfaulting.

As long as you clearly document that the incoming data is going to be modified, it's not a problem. And in a lot of cases, the data either comes from the network or is read from the file - so the buffer is going to be discarded at the end anyway... why not reuse it?

And yes, today it would be easier to make a copy of the data... but remember we are talking about 90's, where RAM is measured in megabytes and your L1 cache may be only 8KB or so.

Re: Use string views instead of passing std:wstring by const&

#52
post #4

Earlier quoted context omitted.

First common 32 bit system was Win 95, which required 4MB of RAM (not GB!). The 4-byte prefix would be considered extremely wasteful in those times - maybe not for a single string, but anytime when there is a list of strings involved, such as constants list. (As a point of reference, Turbo Pascal's default strings still had 1-byte length field). Plus, C-style strings allow a lot of optimizations - if you have a mutab…

> zero copy and zero allocations This is a red herring, because when you actually read the strings out, you still need to iterate through the length for each string—zero copy, zero allocation, but linear complexity. > query file size, allocate buffer once, read it into the buffer, drop some NULL's into strategic positions, maybe shuffle some bytes around for that rare escape case, and you have a whole bunch of C stri…

I don't see what's "red herring" about it - for a reasonable format, any parsing will normally be O(n) complexity, so all we can do is to decrease constant factor.

So _today_ I write parsers in a very different way as well, copying strings is very cheap (today) and not worth it extra complexity.

But remember we are talking about the past, when those conventions are being established. And back in the 90's, zero copy and zero allocations were real advantage. Not in the theoretical CS sense, but in very practical - remember there was _no_ "dynamically resizing vector" in C's (or Pascal's) stdlib, it's just raw malloc() and realloc(), and it is up to you to assemble vector from it as needed. And free()/malloc() overhead was non-trivial, you had to re-use and grow the buffer as needed. And you want to store the parsed data, storing separate length would double your index size! So a parse-in-place + null-terminated strings approach would give you both smaller code and smaller runtime, at the expense of a few sharp corners. But we were all running with scissors back then.

Re: Use string views instead of passing std:wstring by const&

#53
post #19

Earlier quoted context omitted.

I think the concern was conserving memory ( which was scarce back then) and not iterating through each substring.

I am very sceptical about that. Much safer and cleaner languages like ML and Lisp were contemporary to C, and were equally developed on memory-scarce hardware.

Maybe on the high-end machines in some fancy lab somewhere?

All I saw were 386's and 486's, and I am pretty sure every piece of software I ever used was either C or Turbo Pascal or direct assembly. In the mid-90s, Java appeared and I remember how horribly slow those Java apps were compared to C/Pascal code.

Re: Use string views instead of passing std:wstring by const&

#54
post #39

It's best to avoid using std::wstring and other wchar_t-related facilities, as they are highly non-portable across different platforms. If you need to interact with the Win32 API, use char16_t and std::u16string, so that anyone knows it contains a UTF-16 encoded string and knows how to use and process it.

The Windows API uses WCHAR = wchar_t, so if you use char16_t, you have to convert back and forth to avoid running afoul of strict aliasing rules. This imposes conversion costs without benefits; both using wchar_t directly or converting to/from UTF-8 are better.

Or, set up the manifest in your app[1], and just use UTF-8 and `std::string`/`std::string_view` everywhere.

[1]: https://learn.microsoft.com/en-gb/windows/apps/design/global...

Re: Use string views instead of passing std:wstring by const&

#55
post #49

Earlier quoted context omitted.

> I too feel that storing the array's length glued to the array's data is not that good of an idea, it should be stored next to the pointer to the array aka in the array view. That’s not cache-friendly, though. I think the short string optimization (keeping short strings alongside the string length, but allocating a separate buffer for longer strings. See https://devblogs.microsoft.com/oldnewthing/20240510-00/?p=10..…

> That’s not cache-friendly, though. How so? The string implementations in that post are pretty much that: struct string { char* ptr; size_t size; union { size_t capacity; char buf[16]; }; The pointer and the size are stored together, and they may optionally be located right next to the string's actual data, but only for very small, locally-allocated, short-lived strings; but in normal usage, that pointer points some…

> they may optionally be located right next to the string's actual data, but only for very small, locally-allocated, short-lived strings

Only for small strings. Locally allocated and short-lived aren’t required for short string optimization to take an effect.

Also, I can’t find a good reference, but “only for small strings” in many programs means “for most strings”.

Post reply on HN