Axum 0.7.1 uses the CPU more intensively #2381
Replies: 4 comments 37 replies
-
Huh that's very surprising. I honestly have no clue what could be causing this but would be very curious to find out. Are you able to do more investigation? With the data you've provided here is hard to really say much. Can you run a sampling profiler or something to figure out where the CPU is spending its time? |
Beta Was this translation helpful? Give feedback.
-
Hello! I made another experiment (this time on large resources) on a virtual machine with 16 gigabytes of RAM, 8 cores, SSD, OS - Debian 4.19.235-1. Without using docker. The Postgres database is deployed on the current machine (max_connections = 4096). I made 2 simple examples with the following difference:
sample axum 0.6.20
sample axum 0.7.1
I installed the wrk utility on my current machine for load testing and launched both versions of the program on different ports cargo build --release result file size for 0.6.20: 1763912 bytes Next, I ran tests with different parameters and got different metrics. Example: 5 times for 0.7.1: wrk -t8 -c200 -d30s http://127.0.0.1:8865
5 times for 0.6.20: wrk -t8 -c200 -d30s http://127.0.0.1:8866
During the tests, the program on axum 0.6.20 used from 3.06 to 3.37 CPU cores, and the program on axum 0.7.1 from 3.2 to 3.6 CPU cores. Also, version 0.6.20 produced more Requests per second ( better on ~3..8 percents). I repeated this experiment many times to ensure that the results were repeatable. Occasionally the results were similar, but most often the performance of version 0.6.20 was better. Version 0.7.1 never won. I also changed the parameters for wrk: I increased and decreased the number of threads and connections. Perhaps someone else would like to test the same program on different versions of axum (hyper and tower-http). It would be interesting. I'll try to figure out later how to use the sampling profiler to run the program inside a docker image with few resources (for result from first post) |
Beta Was this translation helpful? Give feedback.
-
We are also observing more CPU consumption when migrating to axum 0.7 |
Beta Was this translation helpful? Give feedback.
-
I'm still wondering if we can optimize the body extraction even more. #[async_trait]
impl<S> FromRequest<S> for Bytes
where
S: Send + Sync,
{
type Rejection = BytesRejection;
async fn from_request(req: Request, _: &S) -> Result<Self, Self::Rejection> {
let body_size = req.size_hint().upper(); // <- added
let bytes = req
.into_limited_body()
.collect()
.await
.map_err(FailedToBufferBody::from_err)?
.to_bytes(body_size); // <- changed
Ok(bytes)
}
} And we would change the signature of /// Convert this body into a [`Bytes`].
pub fn to_bytes(mut self, size_hint: Option<usize>) -> Bytes {
match size_hint {
Some(size_hint) => self.bufs.copy_to_bytes(size_hint),
None => self.bufs.copy_to_bytes(self.bufs.remaining()),
}
} This would allow us avoiding to compute |
Beta Was this translation helpful? Give feedback.
-
Hello!
I updated axum from version 0.6.20 to 0.7.1.
According to my metrics, the load on the CPU has increased significantly, although the load on the application has remained the same (300-500 rps). The values, of course, are not too large, but the contrast before and after the update is very noticeable. The load on RAM did not increase or increased slightly. Response latency have not changed either.
My application is a simple service wrapper over a Postgres database (tokio-postgres + bb8).
All my dependencies:
I use docker image with Alpine 3.18.4
Rust version: 1.74.0
Build command: cargo build --target x86_64-unknown-linux-musl --release
I would be grateful if you could share information about how upgrading Axum version affected your CPU load metrics. Thanks!
Beta Was this translation helpful? Give feedback.
All reactions