You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中tokio-postgres驱动性能疑问及优化咨询

tokio-postgres 性能疑问与分析

测试代码

use tokio_postgres::{NoTls};
use tokio::time::Instant;

#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
    let (client, connection) = tokio_postgres::connect("...", NoTls).await?;

    tokio::spawn(async move {
        if let Err(e) = connection.await {
            eprintln!("connection error: {}", e);
        }
    });

    let start = Instant::now();

    let rows = client.query("EXPLAIN ANALYZE SELECT col1 FROM public.test_table WHERE col1 = '15000000'", &[]).await?;
    println!("> Query time: {:?}", start.elapsed());

    let start_time_1 = Instant::now();
    for row in rows {
        let value: &str = row.get(0);
        println!("{}", value);
    }
    println!("> Loop time: {:?} / Full time: {:?}", start_time_1.elapsed(), start.elapsed());

    Ok(())
}

测试结果

> Query time: 2.2302ms
Index Only Scan using idx_test_table_col1 on test_table  (cost=0.43..4.45 rows=1 width=9) (actual time=0.093..0.094 rows=1 loops=1)
  Index Cond: (col1= '15000000'::text)
  Heap Fetches: 0
Planning Time: 0.658 ms
Execution Time: 0.134 ms
> Loop time: 2.3609ms / Full time: 4.8276ms

疑问与解答

1. 为何PostgreSQL执行时间仅0.134ms,tokio-postgres查询耗时却达2.2302ms?

PostgreSQL的Execution Time是数据库内部执行查询的纯计算时间,不包含任何网络传输和客户端处理开销。而tokio-postgres的Query time覆盖了从客户端发起请求到接收完所有结果的完整流程:

  • TCP网络往返延迟(即使本地连接也有协议栈处理开销)
  • PostgreSQL协议的多步消息交互(Parse、Bind、Execute、Sync等步骤的往返通信)
  • 客户端对数据库返回消息的解析、内存分配与结构化处理
  • Tokio异步 runtime 的调度开销

这些额外步骤的总耗时远大于数据库内部执行时间,属于正常现象。

2. 结果迭代为何耗时2.3609ms?能否加速?

这个耗时并非迭代结果本身的开销,核心原因是循环中调用的println!——这是同步的标准输出IO操作,速度极慢,会阻塞异步任务的执行。如果去掉println!,仅保留数据解析逻辑:

for row in rows {
    let _value: &str = row.get(0);
}

迭代耗时会直接降到微秒级别。

tokio-postgres的Row.get()是类型安全的字段解析,本身开销极小,无需额外优化。

3. JDBC测试RPS达15705,Rust代码仅2850,是否Java性能更优?

不是,大概率是测试场景不一致导致的:

  • 连接池配置与复用:确认Rust是否使用了连接池(如bb8-tokio-postgres或deadpool-postgres),且连接数与JDBC一致。如果Rust测试用的是单连接串行执行,RPS自然远低于多连接并发的JDBC测试。
  • 并发模型:JDBC的测试是10用户并发,Rust测试是否开启了同等数量的并发任务?异步代码需要充分利用并发才能发挥性能优势,单任务串行无法体现Rust的性能。
  • 测试逻辑:JDBC是否使用了批量操作、prepared statement复用?Rust侧是否复用了查询的Prepared Statement?
  • RPS计算方式:确认两者的RPS统计范围是否一致(是否包含连接建立时间、是否是稳定运行后的统计)。

调整测试场景,让Rust代码使用连接池并开启同等并发后,RPS应该能达到甚至超过JDBC的水平。


内容的提问来源于stack exchange,提问作者Dvashington

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 05:25:11