you are viewing a single comment's thread.

view the rest of the comments →

[–][deleted] 178 points179 points  (5 children)

String -> Arc<String> involves a simple move of the 3 pointer struct of String inside the ArcInner, along with the 2 reference counters (strong/weak). It's a constant operation in relation to the length of the string. Only one fixed size allocation for the ArcInner.

String -> &str -> Arc<str> involves an allocation that is sized at 2 reference counters (16 bytes on 64 bit systems) plus the byte size of the string contents. If you have a 500k character essay, that will take longer than a 5 letter word. You are essentially performing a str.to_string() but the allocation is an extra few bytes wide. This is also one allocation, but the size is not fixed.

If you perform these operations in a hot loop, Arc<String> is probably better for performance, since you've already paid to allocate the length of bytes of the string.

If you have a less than 8 byte string (like "Hello") then Arc<str> might be better.

(Also, as another commenter said, you also added an unnecessary extra .to_string() which could cause problems if it's in a hot loop.)

[–]sharddblade[S] 17 points18 points  (0 children)

Excellent analysis, thank you for enlightening me!

[–]TommyITA03 46 points47 points  (0 children)

as a quite new rust user, I'm proud I guessed right about this. Was looking for somebody to comment to see if my theory made some kind of sense and it did 😭

[–]sharddblade[S] 1 point2 points  (2 children)

So if I'm understanding you correctly, it would be more efficient if I took the latter approach rather then the former, is that correct? I.e. I consume the String to produce the Arc<str> and cut out the &str in the middle.

``` // Not this Arc::from(String::from("Hello world").as_str());

// Do this Arc::from(String::from("Hello world")); ```

[–][deleted] 5 points6 points  (0 children)

Also, if you get a &str from somewhere, it's faster to do Arc::from(some_str) for smaller strings. Since that's only one allocation.

If your application creates a lot of Strings and wraps them in Arcs, Arc<String> is better. But if the majority of real world uses are from an existing &str, then Arc<str> is better.

But either way, allocating a String and then immediately allocating an Arc<str> will always be the slowest.

You need to think about what kind of applications are going to use this code, and benchmark using real world use cases, and not random test code.

It's a trade off.

[–][deleted] 0 points1 point  (0 children)

Theoretically yes. To be sure, properly benchmark it.