Using Vec<u8> vs Bytes

I occasionally have the problem of choosing between Vec<u8> and Bytes in my code.
From the Bytes documentation:

Bytes is an efficient container for storing and operating on continguous slices of memory. It is intended for use primarily in networking code, but could have applications elsewhere as well.

I heard that Vec is pretty efficient. On the other hand I have seen numerous cases (Mostly for networking code) where Bytes is being used. One example is the tokio_io::Decoder, here.

I couldn’t find any information about how to choose between Vec<u8> and Bytes, I was wondering how do you make this decision. Thanks!

2 Likes

I generally use Vec<u8> unless there’s something from the bytes crate which might make solving a particular problem considerably easier. Most of the time you just need something to hold a bunch of bytes, and Vec is already really well implemented and part of the standard library.

It seems like Bytes would be more applicable if you often need to slice and dice a bunch of bytes, allowing you to pass around a subset of the bytes to multiple people cheaply and without needing to worry about lifetimes. In the tokio_io::Decoder case, using a Bytes probably makes implementation easier because it’s not easy to let futures use borrowed data (that’s why async/await is taking a while to implement, and the reason for withoutboats’ blog series on Pin). If multiple futures need to use bits of the underlying data it’s easy to use reference counting and defer dealing with lifetimes until runtime.

As always, it depends on what you’re trying to do. Most of the time Vec<u8> should be good enough, but you may find a particular problem is easier to solve using Bytes or some other tool.

3 Likes

Hi Michael, thanks for your reply! It is very helpful.
I think that in my case Vec<u8> is enough for everything I need. I will follow your advice on this one and probably stick to it until I need the extra functionality of Bytes.

1 Like