TimonPost / laminar

A simple semi-reliable UDP protocol for multiplayer games
823 stars 66 forks source link

Receiving packets heavily lags after a moment #310

Open LuisMayo opened 11 months ago

LuisMayo commented 11 months ago

When sending and receiving messages at high rates the receiver quickly starts having trouble receiving the messages.

I've made a minimum reproduction repo to showcase this problem: https://github.com/LuisMayo/laminar-testing-latency If you launch a "server" with cargo run and a client with cargo run -- --client a server and a client will run. The client sending messages each 16ms and both of them printing how much time has passed since last sent/received message

If you run them for a while you'll see how the "server" starts outputting higher time differences image

Using --release mode doesn't seem to be of any help. Even if the test uses 16ms. First time I encountered the problem was in fact at a much lower frequency as I was running some tests for a game, each 333ms.

My machine information as output by neofetch

OS: Linux Mint 21.2 x86_64 
Host: 20RA0016SP ThinkPad E14 
Kernel: 5.15.0-89-generic 
Uptime: 2 days, 2 hours, 20 mins 
Packages: 3144 (dpkg), 32 (flatpak) 
Shell: bash 5.1.16 
Resolution: 1920x1080 
DE: Cinnamon 5.8.4 
WM: Mutter (Muffin) 
WM Theme: Mint-Y-Dark-Purple (Mint-Y) 
Theme: Mint-X-Purple [GTK2/3] 
Icons: Mint-Y-Teal [GTK2/3] 
Terminal: gnome-terminal 
CPU: Intel i5-10210U (8) @ 4.200GHz 
GPU: Intel CometLake-U GT2 [UHD Graphics] 
VanderBieu commented 8 months ago

I have encountered similar issue. My case is that I was trying to send multiple images (single image 70kb), it could no longer received any packet right after around 5 images sent.

Dan2552 commented 1 month ago

I was able to reproduce (MacOS arm64; M1) using your example, however adding the following appears to prevent the freezing behavior:

 fn serve() {
     let mut socket = Socket::bind(format!("127.0.0.1:9999")).unwrap();
     let rec = socket.get_event_receiver();
+    let send = socket.get_packet_sender();
     thread::spawn(move || socket.start_polling());
     loop {
+        send.send(Packet::unreliable_sequenced("127.0.0.1:9998".parse().unwrap(), vec![], None));
         let instant = Instant::now();
         let _msg = rec.recv();
         println!("{:?}", instant.elapsed().as_millis());

(I'm not familiar as to why the server sending back messages does this, I just couldn't reproduce it in the example included in the repo, and so tried to work out the difference in behavior and it seemed to be this)

Here's a more full example (derived from this repo's example with your Instant printing):

use std::env::args_os;
use std::time::Duration;
use std::thread;
use std::time::Instant;

use laminar::{ErrorKind, Packet, Socket, SocketEvent};

const SERVER: &str = "127.0.0.1:12351";

fn server() -> Result<(), ErrorKind> {
    let mut socket = Socket::bind(SERVER)?;
    let (sender, receiver) = (socket.get_packet_sender(), socket.get_event_receiver());
    let _thread = thread::spawn(move || socket.start_polling());

    let mut instant = Instant::now();

    loop {
        if let Ok(event) = receiver.recv() {
            match event {
                SocketEvent::Packet(packet) => {
                    let msg = packet.payload();
                    let msg = String::from_utf8_lossy(msg);
                    let ip = packet.addr().ip();

                    println!("Received {:?} from {:?} ({:?})", msg, ip, instant.elapsed().as_millis());
                    instant = Instant::now();
                    sender
                        .send(Packet::reliable_ordered(
                            packet.addr(),
                            format!("Copy that! -- {}", msg).as_bytes().to_vec(),
                            None
                        ))
                        .expect("This should send");
                }
                SocketEvent::Timeout(address) => {
                    println!("Client timed out: {}", address);
                }
                _ => {}
            }
        }
        thread::sleep(Duration::from_millis(1));
    }
}

fn client() -> Result<(), ErrorKind> {
    let addr = "127.0.0.1:12352";
    let mut socket = Socket::bind(addr)?;
    println!("Connected on {}", addr);

    let server = SERVER.parse().unwrap();

    let mut n = 0;

    let mut instant = Instant::now();

    loop {
        let line = format!("hello {}", n);
        n += 1;

        socket.send(Packet::reliable_ordered(
            server,
            line.clone().into_bytes(),
            None
        ))?;

        socket.manual_poll(Instant::now());

        match socket.recv() {
            Some(SocketEvent::Packet(packet)) => {
                if packet.addr() == server {
                    println!("Server sent: {} ({})", String::from_utf8_lossy(packet.payload()), instant.elapsed().as_millis());
                    instant = Instant::now();
                } else {
                    println!("Unknown sender.");
                }
            }
            Some(SocketEvent::Timeout(_)) => {}
            _ => println!("Silence.."),
        }

        thread::sleep(Duration::from_millis(1));
    }
}

fn main() {
    if args_os().any(|element| element == "--client") {
        println!("Client!");
        let _ = client();
    } else {
        let _ = server();
    }
}