Pergi lebih cepat dari Rust?

Jan 07 2023
Tolong seseorang perbaiki kode saya atau sesuatu, karena saya sangat kecewa dengan Rust. Jangan tembak kurir di sini juga (jangan ragu untuk menembak saya jika itu adalah kesalahan kode buruk saya).

Tolong seseorang perbaiki kode saya atau sesuatu, karena saya sangat kecewa dengan Rust. Jangan tembak kurir di sini juga (jangan ragu untuk menembak saya jika itu adalah kesalahan kode buruk saya).

Saya tahu hampir setiap perbandingan performa antara Go dan Rust menunjukkan performa Rust yang lebih baik, tetapi apakah selalu demikian? Sepertinya tidak, dan sebenarnya hasil yang akan saya bagikan adalah kinerja yang sangat buruk dari Rust dan dengan semua hype saya sangat kecewa.

Hasil dari Go — berlari dengango build && ./go_test

wrk -t 25 -c 100 -d 60s --timeout 8s http://127.0.0.1:8080/test_top25
Running 1m test @ http://127.0.0.1:8080/test_top25
  25 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     2.37s   399.13ms   4.75s    81.81%
    Req/Sec     2.76      3.37    30.00     86.68%
  2474 requests in 1.00m, 378.22MB read
Requests/sec:     41.18
Transfer/sec:      6.30MB

wrk -t 25 -c 100 -d 60s --timeout 8s http://127.0.0.1:8000/test_top25
Running 1m test @ http://127.0.0.1:8000/test_top25
  25 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     3.30s   560.20ms   6.08s    76.31%
    Req/Sec     2.75      3.88    30.00     84.61%
  1769 requests in 1.00m, 272.14MB read
Requests/sec:     29.43
Transfer/sec:      4.53MB

Semua tes kinerja yang saya temukan adalah dengan semacam data palsu, apakah kinerja Rust dalam pengaturan aplikasi dunia nyata tidak sebagus yang dibuat semua orang? Apakah peti/perpustakaan yang digunakan? Saya tidak yakin, jadi mari kita lihat …

use actix_web::{web, App, HttpResponse, HttpServer};
use sqlx::postgres::PgPoolOptions;
use sqlx::types::JsonValue;

#[derive(sqlx::FromRow, serde::Serialize)]
struct Snapshot {
    Resource: serde_json::Value
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    let pool = PgPoolOptions::new()
        .max_connections(25)
        .min_connections(25)
        .connect("<postgres_url>").await
        .expect("Failed to create pool.");

    HttpServer::new(move || {
        App::new()
            .wrap(actix_web::middleware::Compress::default())
            .app_data(web::Data::new(pool.clone()))
            .route("/test_top25", web::get().to(|pool: web::Data<sqlx::PgPool>| async move {
                let rows = sqlx::query_as::<_, Snapshot>("SELECT <query> LIMIT 25")
                    .fetch_all(&**pool).await.unwrap();
                HttpResponse::Ok().json(serde_json::json!({ "message": rows }))
            }))
    })
    .client_request_timeout(std::time::Duration::from_secs(60))
    .bind(("0.0.0.0", 8000))?
    .run().await
}

package main

import (
 "context"
 "fmt"
 "net/http"

 "github.com/gin-gonic/gin"
 "github.com/jackc/pgx/v5"
 "github.com/jackc/pgx/v5/pgxpool"
)

func setupRouter() *gin.Engine {
 r := gin.Default()

 psqlInfo := "<postgres_url>"

 config, err := pgxpool.ParseConfig(psqlInfo)
 config.MaxConns = 25
 config.MinConns = 25

 pool, err := pgxpool.NewWithConfig(context.Background(), config)

 r.GET("/test_top25", func(c *gin.Context) {
  res, err := pool.Query(context.Background(), "SELECT <query> LIMIT 25")

  rows, err := pgx.CollectRows(res, pgx.RowTo[any])

  c.JSON(http.StatusOK, gin.H{
   "message": rows,
  })
 })

 return r
}

func main() {
 r := setupRouter()
 r.Run(":8080")
}

Seseorang cepat, perbaiki kode Rust saya, karena menurut SEMUA ORANG hal ini seharusnya tidak terjadi. Saya pikir saya cukup baik setidaknya dengan Rust, dan saya belum pernah menulis baris Go dalam hidup saya sebelumnya, jadi fakta bahwa saya bisa mendapatkan kinerja yang lebih baik dari bahasa yang baru saja saya pelajari adalah mengecewakan.

Sebagai catatan, saya memang mencoba tes ini dengan beberapa parameter berbeda; jumlah utas berbeda, jumlah koneksi berbeda, rentang waktu berbeda, dll., tetapi Rust hanya mengalahkan Go dalam satu set yang terdiri dari sekitar 15 pengujian.