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

Rust实现Protohackers Prime Time多客户端测试超时求助

Protohackers Prime Time挑战多客户端超时问题解决

我正在学习Rust,尝试完成Protohackers的Prime Time挑战,单客户端测试已通过,但多客户端测试出现60秒超时失败,测试日志如下:

[Mon Nov 28 14:21:10 2022 UTC] [0simple.test] NOTE:check starts
[Mon Nov 28 14:21:10 2022 UTC] [0simple.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:21:13 2022 UTC] [0simple.test] NOTE:handled all 25 requests correctly
[Mon Nov 28 14:21:13 2022 UTC] [0simple.test] PASS
[Mon Nov 28 14:21:14 2022 UTC] [1multiclient.test] NOTE:check starts
[Mon Nov 28 14:21:15 2022 UTC] [1multiclient.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:21:15 2022 UTC] [1multiclient.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:21:15 2022 UTC] [1multiclient.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:21:15 2022 UTC] [1multiclient.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:21:15 2022 UTC] [1multiclient.test] NOTE:connected to 213.89.253.71 port 5006
[Mon Nov 28 14:22:14 2022 UTC] [1multiclient.test] FAIL:alarm timeout after 60 seconds

我的实现代码:

use std::{net::TcpListener, io::{Result, Read}, thread};
use serde_json::json;
use serde::{Deserialize};
use std::io::Write;

#[derive(Deserialize, Debug)]
struct Message {
    method: String,
    number: i64
}

impl Message {
    fn is_ok(&self) -> bool {
        if self.method == "isPrime"{
            return true;
        }
        return false; 
    }

    fn is_prime(&self) -> bool {
        if self.number <= 1{
            return false; 
        }
        for i in  2..self.number {
            if self.number % i ==0 {
                let res = self.number % i; 
                println!("{res}"); 
                return false; 
            }
        }
        return true; 
    }

    fn get_variables(&self){
        println!("Method is: {0}, Number is: {1} ", self.method, self.number);
    }
    
}

fn main() -> Result<()>{
    let addr= "192.168.0.9:5006"; 
    let listener= TcpListener::bind(addr)?; 
    for stream in listener.incoming(){
        let _ :thread::JoinHandle<Result<()>> = thread::spawn(move || {
            loop {
                let mut m = serde_json::Deserializer::from_reader(stream.as_ref().unwrap());
                let msg = Message::deserialize(&mut m);

                match msg{
                    Ok(msg)=>{
                        if msg.is_ok(){
                            let ret_msg = json!({"method":"isPrime","prime":msg.is_prime()});
                            serde_json::to_writer(stream.as_ref().unwrap(), &ret_msg).unwrap();
                            stream.as_ref().expect("Error").write(b"\n").unwrap(); 
                        }
                     }, 
                    _ => {
                        break Ok(()); 
                    }
                }
            }
        });
    }
    Ok(())
}

问题分析与修复方案

1. 质数判断效率极低(核心超时原因)

原is_prime函数遍历从2到目标数的所有整数,对于大数字(比如接近i64上限的数)会花费数十秒甚至更久,多客户端场景下只要有一个请求卡住,就会触发测试超时。

优化后的质数判断逻辑:

  • 直接排除小于等于1的数、偶数(除了2)
  • 仅遍历到目标数的平方根,且只检查奇数,大幅减少循环次数
fn is_prime(&self) -> bool {
    match self.number {
        n if n <= 1 => false,
        2 => true,
        n if n % 2 == 0 => false,
        _ => {
            let sqrt_n = (self.number as f64).sqrt() as i64;
            (3..=sqrt_n).step_by(2).all(|i| self.number % i != 0)
        }
    }
}

2. Stream可变借用错误

serde_json::Deserializer::from_reader需要一个实现Read的可变引用,原代码中stream.as_ref().unwrap()得到的是不可变引用,无法正确读取数据流,多客户端下会引发读取异常。

3. JSON反序列化方式错误

每次循环创建新的Deserializer,无法正确处理同一个TCP连接中的多个JSON请求。应该复用Deserializer,通过连续反序列化来逐个读取请求。

4. 未刷新输出缓冲区

写入响应后没有调用flush(),可能导致响应滞留在缓冲区,客户端无法及时收到数据,引发超时。

修正后的完整代码

use std::{net::TcpListener, io::{Result, Read, Write}, thread};
use serde_json::json;
use serde::{Deserialize};

#[derive(Deserialize, Debug)]
struct Message {
    method: String,
    number: i64
}

impl Message {
    fn is_prime(&self) -> bool {
        match self.number {
            n if n <= 1 => false,
            2 => true,
            n if n % 2 == 0 => false,
            _ => {
                let sqrt_n = (self.number as f64).sqrt() as i64;
                (3..=sqrt_n).step_by(2).all(|i| self.number % i != 0)
            }
        }
    }
}

fn main() -> Result<()>{
    let addr = "192.168.0.9:5006"; 
    let listener = TcpListener::bind(addr)?; 
    
    for stream_result in listener.incoming() {
        let _ = thread::spawn(move || -> Result<()> {
            let mut stream = stream_result?;
            let mut deserializer = serde_json::Deserializer::from_reader(&mut stream);
            
            loop {
                match Message::deserialize(&mut deserializer) {
                    Ok(msg) => {
                        if msg.method == "isPrime" {
                            let prime = msg.is_prime();
                            let ret_msg = json!({"method": "isPrime", "prime": prime});
                            serde_json::to_writer(&mut stream, &ret_msg)?;
                            stream.write_all(b"\n")?;
                            stream.flush()?;
                        }
                    }
                    Err(_) => {
                        // 连接断开或解析失败时退出循环
                        break Ok(());
                    }
                }
            }
        });
    }
    
    Ok(())
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 03:55:28