Skip to content

Commit

Permalink
Move tasks over to rayon thread pool + adjust db connection pool
Browse files Browse the repository at this point in the history
The rayon threadpool alone was not enough to solve perf problems with
offloading these tasks. I had thought it was related to queuing or too
much parallelism and it (kinda) was but really it was exhaustion of
the db connection pool (default 10) with a high timeout (30s).

These two adjustments combined now at least prevent the server from
going unresponsive when I hit it with 5000 rps. The server _before_
any offloading (just running all this on the Tokio runtime threads)
is still lower latency. It's probable that this "blocking/CPU work"
is just still so little the thread coordination overhead is higher
than the work at hand.
  • Loading branch information
davidwilemski committed Jan 29, 2024
1 parent e78cb9d commit 5f06bdf
Show file tree
Hide file tree
Showing 5 changed files with 48 additions and 10 deletions.
31 changes: 31 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -36,3 +36,4 @@ http = "0.2"
toml = "0.5.10"
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["env-filter", "tracing-log"] }
tokio-rayon = "2.1.0"
2 changes: 1 addition & 1 deletion src/handler.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ pub trait WithDB {
#[tracing::instrument(level = "debug", skip(self))]
fn dbconn(&self) -> Result<PooledConnection<ConnectionManager<SqliteConnection>>, DBError> {
self.dbpool().get().map_err(|e| {
error!("{:?}", e);
error!("error getting connection: {:?}", e);
DBError::new()
})
}
Expand Down
16 changes: 8 additions & 8 deletions src/handlers/fetch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,18 +31,18 @@ pub async fn get_post_handler(
let slug_clone = url_slug.clone();
let mut slug_conn = db.dbconn()?;
let mut post: Post =
tokio::task::spawn_blocking(move || {
tokio_rayon::spawn_fifo(move || {
Post::by_slug(&slug_clone)
.first::<Post>(&mut slug_conn)
.map_err(|e| handle_db_errors(e))
})
.instrument(debug_span!("post_by_slug"))
.await.map_err(|e| Into::<ServerError>::into(e))??;
.await?;

let post_id = post.id;
let mut tags_conn = db.dbconn()?;
let tags_fut =
tokio::task::spawn_blocking(move || {
tokio_rayon::spawn_fifo(move || {
use crate::schema::categories::dsl as category_dsl;
category_dsl::categories
.select(category_dsl::category)
Expand All @@ -53,7 +53,7 @@ pub async fn get_post_handler(
.instrument(debug_span!("tags_by_post_id"));

let photos_fut =
tokio::task::spawn_blocking(move || {
tokio_rayon::spawn_fifo(move || {
use crate::schema::photos::dsl as photos_dsl;
photos_dsl::photos
.select((photos_dsl::url, photos_dsl::alt))
Expand All @@ -64,8 +64,8 @@ pub async fn get_post_handler(
.instrument(debug_span!("photos_by_post_id"));

let (tags_result, photos_result)= join!(tags_fut, photos_fut);
let tags = tags_result.map_err(|e| Into::<ServerError>::into(e))??;
let photos = photos_result.map_err(|e| Into::<ServerError>::into(e))??;
let tags = tags_result?;
let photos = photos_result?;

debug!("input datetime: {:?}", post.created_at);
let datetime = post_util::get_local_datetime(&post.created_at, &site_config.micropub.current_timezone_offset).map_err(|e| {
Expand All @@ -77,11 +77,11 @@ pub async fn get_post_handler(
post.created_at = datetime.to_rfc3339();

let post_view =
tokio::task::spawn_blocking(move || {
tokio_rayon::spawn_fifo(move || {
PostView::new_from(post, tags, DateView::from(&datetime), photos)
})
.instrument(debug_span!("create post view model"))
.await.map_err(|e| Into::<ServerError>::into(e))?;
.await;

let _templates = debug_span!("template_render");
_templates.in_scope(|| {
Expand Down
8 changes: 7 additions & 1 deletion src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ extern crate diesel;
#[macro_use]
extern crate serde_json;

use std::time::Duration;

use diesel::prelude::SqliteConnection;
use diesel::r2d2;

Expand All @@ -29,5 +31,9 @@ pub fn new_dbconn_pool(
db_file: &str,
) -> Result<r2d2::Pool<r2d2::ConnectionManager<SqliteConnection>>, anyhow::Error> {
let manager = r2d2::ConnectionManager::<SqliteConnection>::new(db_file);
Ok(r2d2::Pool::new(manager)?)
let pool = r2d2::Builder::new()
.max_size(36)
.connection_timeout(Duration::new(5, 0))
.build(manager)?;
Ok(pool)
}

0 comments on commit 5f06bdf

Please sign in to comment.