Q:

What tools does Rust provide to avoid copies when using MPSC channels?

I'm creating a multithreaded application using mpsc to share memory between my threads:
use std::thread;
use std::sync::mpsc::{Sender, Receiver};

#[derive(Debug)]
struct Msg {
    pub content: Vec<i16>,
    /* ... */
}

#[derive(Debug)]
struct MsgBack {
    pub content: Vec<i16>,
    pub new_content: Vec<i16>,
    /* ... */
}

fn child(rx: mpsc::Receiver<Msg>, tx: mpsc::Sender<MsgBack>) {
    let message = rx.recv().unwrap();
    let new_content = message.content.iter().map(|x| -x).collect();

    tx.send(MsgBack { // The memory is moved/copied
        content: message.content,
        new_content: new_content,
    });
}

fn main() {
    let (tx, rx): (Sender<Msg>, Receiver<Msg>) = mpsc::channel();
    let (tx_back, rx_back): (Sender<MsgBack>, Receiver<MsgBack>) = mpsc::channel();

    thread::spawn(move || {
        child(rx, tx_back);
    });

    let message = Msg {
        content: (0..100).map(|x| x).collect(), // Dummy initialisation
    };
    println!("{:#?}", message);
    tx.send(message).unwrap(); // The memory is moved/copied

    let answer = rx_back.recv().unwrap();
    println!("{:#?}", answer);
}

I did some profiling and I saw that sending the data is responsible for 1/3 of the execution time in my real program (which sends more than just a Vec).
I want to keep this code structure but avoid moves/copies when sending a message to save a lot of time.

A:

Move of a Vec doesn't move its content, but only the 3-word "header". Therefore, unless your MsgBack contains a lot of other fields or large  fixed-size arrays inline, it should be rather cheap to move.
In general, you can put things in Box to allocate them on the heap, so then the Box<T> itself is only pointer-sized. "Moving" of the Box doesn't move any data, only copies the pointer.

If your actual iterators are more complex than your example and don't have useful size_hint, you may be seeing memcpy from .collect() reallocating the vector as it grows. You can avoid that by pre-allocating required size:
Instead of:
let dst = iterator.collect();

use:
let mut dst = Vec::with_capacity(required_size);
dst.extend(iterator);

