Rustは、同時実行ストレステストを使用して、単純で高度に同時実行のhttpサービス(純粋な標準ライブラリ、コンパイル後168kb)を作成します。

この単純な錆プログラムは2つだけのファイルを持っていますmain.rsし、index.html

releaseコンパイルされたバイナリファイルのサイズは約168kbであり、標準ライブラリのみが使用されます(公式のWebサイトの場合と同様ですが、多少異なります)

ルーティング機能の簡単な実装、ローカルファイルの読み取り...最適化された公式Webサイトの場合(たとえば、512バッファが小さすぎる)


次に、書き始めます。

最初にディレクトリを見つけて作成しますindex.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>Hello!</title>
  </head>
  <body>
    <h1>Hello!</h1>
    <p>Hi from Rust</p>
  </body>
</html>

次に作成しますmain.rs

use std::fs::File;
use std::io::prelude::*;
use std::net::TcpListener;
use std::net::TcpStream;
use std::thread;

const CRLF: &str = "\r\n";
fn main() {
    
    
    let listener = TcpListener::bind("127.0.0.1:8080").unwrap();
    for stream in listener.incoming() {
    
    
        let stream = stream.unwrap();
        thread::spawn(|| handle_connection(stream));
    }
}

// 首页
fn handle_index() -> (String, String) {
    
    
    (file_return("index.html"), status(200, "OK"))
}

// 404页面
fn handle_404() -> (String, String) {
    
    
    (String::new(), status(200, "OK"))
}

fn handle_connection(mut stream: TcpStream) {
    
    
    let mut buffer= [0; 4096];
    stream.read(&mut buffer).unwrap();

    let _matched = |route: &str| matched(&buffer, route);
    let _write = |(contents, status)| write(stream, contents, status);

    // 路由处理
    if _matched("/") {
    
    
        _write(handle_index());
    } else {
    
    
        _write(handle_404());
    }
}

// 路由匹配
fn matched(buffer: &[u8; 4096], route: &str) -> bool {
    
    
    let s = format!("GET {} HTTP/1.1{}", route, CRLF);
    buffer.starts_with(s.as_bytes())
}

// 读取本地文件内容
fn file_return(file_name: &str) -> String {
    
    
    let mut file = File::open(file_name).unwrap();
    let mut contents = String::new();
    file.read_to_string(&mut contents).unwrap();
    contents
}

fn status(code: i32, text: &str) -> String {
    
    
    format!("HTTP/1.1 {} {}{}", code, text, CRLF)
}

// 将响应写出到流
fn write(mut stream: TcpStream, contents: String, status: String) {
    
    
    let content_type = format!("Content-Type: text/html;charset=utf-8{}", CRLF);
    let server = format!("Server: Rust{}", CRLF);
    let content_length = format!("Content-Length: {}{}", contents.as_bytes().len(), CRLF);
    let response = format!(
        "{0}{1}{2}{3}{4}{5}",
        status, server, content_type, content_length, CRLF, contents
    );
    stream.write(response.as_bytes()).unwrap();
    stream.flush().unwrap();
}

コマンドラインを開いてreleaseコンパイルします(最大最適化、ファイルサイズ168kb):

rustc main.rs -C opt-level=3 -C debuginfo=0

あなたはそれを直接実行する場合はrustc main.rsあなたがされdebug、コンパイル、およびファイルのサイズは約です210kb

ここに写真の説明を挿入

コンパイル後に生成されますmain.exe(Unixシステムでは.exeサフィックスはありません)。実行します。

./main

次に、URLを開きます。

http://127.0.0.1:8080

あなたは私たちのページを見ることができます!

ここに写真の説明を挿入


ストレステストを試して、Rustによって作成されたおもちゃのHTTPサーバーがどのように機能するかを確認できます。

loadtestストレステストに使用することにしました。これはnpmnode.js環境で実行する必要があるパッケージです。
npmアドレス:https//www.npmjs.com/package/loadtest

インストール:npm install -g loadtest

次に、テストコマンドを実行します。

loadtest -t 10 -c 100 "http://127.0.0.1:8080/"

コマンドについて簡単に説明します。

  • -t 10 代表的なテストは最大10秒間実行されます
  • -c 100 同時100の数を表します
  • "http://127.0.0.1:8080/"テストURL(ここで/終了する必要があります

試験結果:

  • このRustHTTPサービスでは100の同時リクエストを食べるのは簡単なようです。私のマシン構成では、1秒あたり4091のリクエストを処理できます。10秒で合計40915のリクエストが処理されます。間違ったリクエストの数は0です。各リクエストには平均24ミリ秒かかります。

ここに写真の説明を挿入
したがって、同時実行数を10000に直接増やすとどうなりますか。

  • 同時実行数が10,000未満の場合、このプログラムは1秒あたり3158リクエストしか処理できず、各リクエストの平均処理時間も2.6秒になり、はるかに遅くなりますが、それでも間違ったリクエストはなく、このサービスを示しています。パフォーマンスはまだOKです(テスト中、メモリ使用量は最大200MBです

ここに写真の説明を挿入
それから私は同時実行の数を増やし続けました、そして同時の数は来ました16000

  • 各リクエストの処理時間は現在約4秒で、ほぼ時間切れになっていることがわかります。
    ここに写真の説明を挿入
    同時実行性は増加し続けており、次のようになり17000ます。

  • おもちゃのHTTPサービスが完全に崩壊し、すべてのリクエストが間違っていることがわかります。これは、17,000の同時実行で制限に達したことを示しています。(それは私のシステムの上限であるはずです)

ここに写真の説明を挿入

これは、Rust言語のパフォーマンスが本当に優れていることを示しています。この168kbのおもちゃのHTTPサービスは、16000の同時実行に耐えることができますが、これは簡単ではありません...

もちろん、同時実行性が高いほど、プログラムのメモリ使用量が多くなります。これは、Rustが処理のために多くの新しいスレッドを作成する必要があるためです。

また、今回作成したHTTPサービスは非同期を使用せず、マルチスレッドのみを使用し、Rustのパフォーマンスは完全には示されませんでした。

Rustの非同期を見ることができます:
https //crates.io/crates/futures
https://github.com/tokio-rs/tokio

おすすめ

転載: blog.csdn.net/qq_26373925/article/details/109187251
おすすめ