Converting &str: to_string vs to_owned (with two benchmarks)

Eric Opines
3 min readJan 2, 2016

--

I’m working on my first crate (aws-elb-abacus, nothing on master yet but getting close). It’s a really trivial problem to solve and I’ve already put an equivalent solution, written in Go, into production which made it the perfect problem for my first crate.

The important part of the code parses a space separated set of values (AWS docs) and then converts some of the values to more refined representations for further processing. There’s a lot of string work being done.

Coincidentally, I was reading what others wrote after reviewing a Rust codebase and ran across the following statement about working with strings.

Don’t use to_string on strs; it’s generic, which makes it slow. Prefer into or to_owned.

There was a response from Steve Klabnik, he of the Rust Book, explaining a bit more.

To elaborate here a bit, it’s not exactly that generics are slow, it’s that it could be faster if it took advantage of it being &str specifically, which it can’t do. Yet…

I was using to_string for everything in my crate (and everything I’ve written in Rust to date) so I was more than a little curious.

A quick google search and a little reading brought me to this Q&A which had the best explanation of the details.

You should always be using to_owned(). to_string() is the generic conversion to a String from any type implementing the ToString trait. It uses the formatting functions and therefor might end up doing multiple allocations and running much more code than a simple to_owned() which just allocates a buffer and copies the literal into the buffer.

Totally reasonable but how much does it matter in the real world? I had to do some testing.

I have been benchmarking my code as I worked through my crate so it was a simple matter of swapping out the method calls and running the benchmarks.

I’ve been benchmarking using two methods. The first benchmark uses Rust nightly’s support for benchmarking. I’m not an advocate of this kind of benchmarking normally. Most of the time the results are absolute nonsense and have no bearing on production results either because the benchmark is flawed or because the developer is testing the wrong section of code to begin with. But I am curious about Rust’s built in benchmarking support and want to keep track of developments of that feature as Rust moves forward. What better way to do so than having your own code.

These are the results.

using to_string: test bench_parse_line ... bench:       2,299 ns/iter (+/- 259)using to_owned: test bench_parse_line … bench: 2,097 ns/iter (+/- 348)

It does appear there’s a significant performance increase of about 9%.

I ran it a few times and the numbers are about the same every time.

But, again, I’m not a fan of micro benchmarks. So how about a real world test?

Throughout my development I’ve been running a CLI tool I wrote to use the crate against a real set of AWS ELB logs.

These are the results of the change from to_string to to_owned against a real set of files.

using to_string:Processed 121 files having 9340036 records in 32010 milliseconds.using to_owned:Processed 121 files having 9340036 records in 28462 milliseconds.

Switching to to_owned produced a performance increase of about 11%. That’s the real time it would take running in production which is much more important to me than the micro benchmark. That being said, the results of both benchmarks are remarkably close and the CLI tool doesn’t do much more than the micro benchmark at the moment.

The numbers are reasonable given the stated reasons for using to_owned instead of to_string.

I’m convinced to_owned is the right method to use and does produce a performance increase for programs doing lots of string conversions.

Further, and maybe more importantly, I’m reminded that reviewing code you didn’t write and reading the reviews of others is a really, really important part of becoming a better developer. The Rust community excels in this area. Generally, if someone posts a request for a code review, at least one person and, more often than not multiple people, will take the time to do the review. I’ll be submitting a code review request soon.

--

--

Eric Opines

I talk to computers. My aura is a series of 1’s and 0’s. I’m a technologist. I’m a renaissance man. I’m Mr. Average trying to do things that are hard.