Почему асинхронные версии эхо-сервера TCP используют в 50 раз больше памяти, чем синхронные? - PullRequest
5 голосов
/ 04 августа 2020

У меня есть простой TCP-эхо-сервер с использованием стандартной библиотеки:

use std::net::TcpListener;

fn main() {
    let listener = TcpListener::bind("localhost:4321").unwrap();
    loop {
        let (conn, _addr) = listener.accept().unwrap();
        std::io::copy(&mut &conn, &mut &conn).unwrap();
    }
}

Он использует около 11 МБ памяти:

standard library

Tokio

If I convert it to use tokio:

tokio = { version = "0.2.22", features = ["full"] }
use tokio::net::TcpListener;

#[tokio::main]
async fn main() {
    let mut listener = TcpListener::bind("localhost:4321").await.unwrap();
    loop {
        let (mut conn, _addr) = listener.accept().await.unwrap();
        let (read, write) = &mut conn.split();
        tokio::io::copy(read, write).await.unwrap();
    }
}

Он использует 607 МБ памяти:

tokio

async_std

Similarly, with async_std:

async-std = "1.6.2"
use async_std::net::TcpListener;

fn main() {
    async_std::task::block_on(async {
        let listener = TcpListener::bind("localhost:4321").await.unwrap();
        loop {
            let (conn, _addr) = listener.accept().await.unwrap();
            async_std::io::copy(&mut &conn, &mut &conn).await.unwrap();
        }
    });
}

Он также использует 607 МБ памяти:

async_std

Почему асинхронные версии программы используют в 55 раз больше памяти, чем синхронные?

Ответы [ 2 ]

5 голосов
/ 04 августа 2020

Вы должны посмотреть на столбец RES. Один использует 1,0 МБ, другой - 1,6 МБ.

Большинство из них, вероятно, будут постоянными накладными расходами, необходимыми для запуска среды выполнения tokio и пула потоков для нее.

2 голосов
/ 05 августа 2020

Я пробовал это здесь, и, как вы сказали в комментариях, есть несколько блоков по 64 МБ:

==> pmap -d $(pidof tokio)
3605:   target/release/tokio
Address           Kbytes Mode  Offset           Device    Mapping
…
0000555b2a634000     132 rw--- 0000000000000000 000:00000   [ anon ]
00007f2fec000000     132 rw--- 0000000000000000 000:00000   [ anon ]
00007f2fec021000   65404 ----- 0000000000000000 000:00000   [ anon ]
00007f2ff0000000     132 rw--- 0000000000000000 000:00000   [ anon ]
00007f2ff0021000   65404 ----- 0000000000000000 000:00000   [ anon ]
00007f2ff4000000     132 rw--- 0000000000000000 000:00000   [ anon ]
00007f2ff4021000   65404 ----- 0000000000000000 000:00000   [ anon ]
…

Эти блоки не доступны для чтения и записи, поэтому они не отображаются и не используют любая память. Они просто представляют собой зарезервированное адресное пространство.

Более того, как вы можете видеть, каждый из этих 65404K блоков идет сразу после блока 132K. Поскольку 65404 + 132 - это ровно 65536, я подозреваю, что эти блоки представляют собой адресное пространство, которое зарезервировано на тот случай, если среде выполнения потребуется увеличить один из этих 132 КБ блоков позже. Было бы интересно посмотреть, как все будет выглядеть через пару часов и несколько тысяч подключений.

...