#tokio performance

38 messages · Page 1 of 1 (latest)

eternal knot
#

Hello
I wrote the following code

use tokio::time::{sleep, Duration};
use tokio::sync::Mutex;
use std::sync::Arc;
use reqwest;
use std::time::Instant;

#[tokio::main]
async fn main() {
    let totalreqs = Arc::new(Mutex::new(0));
    let reqs = Arc::new(Mutex::new(0));

    let totalreqs_clone = Arc::clone(&totalreqs);
    let reqs_clone = Arc::clone(&reqs);

    tokio::spawn(async move {
        let start = Instant::now();
        loop {
            sleep(Duration::from_secs(1)).await;
            let mut totalreqs = totalreqs_clone.lock().await;
            let mut reqs = reqs_clone.lock().await;
            *totalreqs += *reqs;
            print!(
                "reqs/sec: {} average reqs/sec: {} total: {}     \r",
                *reqs,
                *totalreqs as f64 / start.elapsed().as_secs_f64(),
                *totalreqs
            );
            *reqs = 0;
        }
    });

    for _ in 0..500 {
        let reqs_clone = Arc::clone(&reqs);
        tokio::spawn(async move {
            loop {
                let resp = reqwest::get("http://ipinfo.io/ip").await;
                if let Ok(resp) = resp {
                    if resp.status().is_success() {
                        let mut reqs = reqs_clone.lock().await;
                        *reqs += 1;
                    }
                }
            }
        });
    }

    tokio::signal::ctrl_c().await.unwrap();
}

But its tooo slow that it only updates ever like 5 seconds or more

How to take advantage of whole cpu when running it

Should i use std threads

Thanks

primal solar
#

I don't think benchmarking against a random website is very useful

#

you'll be limited by your connection and whatever the website will accept

#

running a simple python server on the same machine and benchmarking that resulted in ~400 reqs/s for me

#

but the rust app was chilling at about half a core used, while python was using severals, so I'm pretty sure the bottleneck was the python server and not the rust client

eternal knot
#

Ok great idea i will run axum server to test

#

But for some reason the title was getting updated every like 5 or 10 seconds for me

primal solar
#

the buffer flushes when it's full or when it encounters a \n

#

I don't think a \r will flush the buffer

#

you could flush it manually, or just print a \n somewhere

#

so your text was never getting to the console

eternal knot
#

Ok tysm i try when home

eternal knot
#

ye man

#

tysm

#

the issue was \n thingy

eternal knot
#
use tokio::time::{sleep, Duration};
use tokio::sync::Mutex;
use std::sync::Arc;
use reqwest;
use std::time::Instant;
use std::io::{self, Write};

#[tokio::main]
async fn main() {
    let totalreqs = Arc::new(Mutex::new(0));
    let reqs = Arc::new(Mutex::new(0));

    let totalreqs_clone = Arc::clone(&totalreqs);
    let reqs_clone = Arc::clone(&reqs);

    tokio::spawn(async move {
        let start = Instant::now();
        loop {
            sleep(Duration::from_secs(1)).await;
            let mut totalreqs = totalreqs_clone.lock().await;
            let mut reqs = reqs_clone.lock().await;
            *totalreqs += *reqs;
            print!(
                "reqs/sec: {} avg: {} total: {}     \r",
                *reqs,
                *totalreqs as f64 / start.elapsed().as_secs_f64(),
                *totalreqs
            );
            io::stdout().flush().unwrap();
            *reqs = 0;
        }
    });

    for _ in 0..1000 {
        let reqs_clone = Arc::clone(&reqs);
        tokio::spawn(async move {
            loop {
                let resp = reqwest::get("http://localhost:8080/").await;
                if let Ok(resp) = resp {
                    if resp.status().is_success() {
                        let mut reqs = reqs_clone.lock().await;
                        *reqs += 1;
                    }
                }
            }
        });
    }

    tokio::signal::ctrl_c().await.unwrap();
}
#
package main

import (
    "net/http"
    "runtime"
    "sync"
    "time"
)

func main() {
    runtime.GOMAXPROCS(1)
    totalreqs := 0
    reqs := 0
    reqsMu := sync.Mutex{}
    go func() {
        start := time.Now()
        for {
            time.Sleep(time.Second)
            totalreqs += reqs
            print("reqs/sec: ", reqs, " avg: ", totalreqs/int(time.Since(start).Seconds()), " total: ", totalreqs, "     \r")
            reqs = 0
        }
    }()

    for i := 0; i < 1000; i++ {
        go func() {
            for {
                resp, err := http.Get("http://localhost:8081/")
                if err != nil || resp.StatusCode != 200 {
                    continue
                }
                reqsMu.Lock()
                reqs++
                reqsMu.Unlock()
            }
        }()
    }
    select {}
}
#

why the go code faster than rust

#

and

#

cpu usage for rust is just 20% go is 80%

#

and rust program freeze

#

till i close go one

#

🤯

dull thicket
#

I wouldn't be shocked if you were holding some underlying OS lock

eternal knot
#

but probably no

#

let me try

#

10 sec alone

#

10 sec alone

eternal knot
eternal knot
#

the local host server im running

use actix_web::{web, App, HttpResponse, HttpServer, Responder};

async fn greet() -> impl Responder {
    HttpResponse::Ok().body("Hello, world!")
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    HttpServer::new(|| {
        App::new()
            .route("/", web::get().to(greet))
    })
        .bind("127.0.0.1:8081")?
        .run()
        .await
}
#

2 times

#

8080 for rust

#

8081 for go

vivid lion
#

Did you run rust in release mode?