Skip to content

Commit

Permalink
update trillium framework benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
jbr committed Dec 1, 2023
1 parent 90f38de commit f4513e7
Show file tree
Hide file tree
Showing 18 changed files with 1,581 additions and 814 deletions.
2,052 changes: 1,334 additions & 718 deletions frameworks/Rust/trillium/Cargo.lock

Large diffs are not rendered by default.

22 changes: 12 additions & 10 deletions frameworks/Rust/trillium/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,22 @@ edition = "2021"

[dependencies]
askama = "0.11.1"
fastrand = "1.7.0"
futures-lite = "1.12.0"
futures-util = "0.3.21"
serde = { version = "1.0.136", features = ["derive"] }
serde_json = "1.0.79"
trillium = "0.2.2"
fastrand = "2.0.1"
futures-lite = "2.0.1"
serde = { version = "1.0.193", features = ["derive"] }
serde_json = "1.0.108"
trillium = "0.2.11"
trillium-api = "0.1.0"
trillium-askama = "0.3.0"
trillium-async-std = "0.2.0"
trillium-logger = "0.4.0"
trillium-router = "0.3.2"
trillium-smol = "0.3.1"
trillium-logger = "0.4.3"
trillium-router = "0.3.5"
unicycle = "0.9.4"
env_logger = "0.10.1"
moka = { version = "0.12.1", features = ["future"] }

[dependencies.sea-orm]
version = "0.6.0"
version = "0.12.7"
default-features = false
features = ["runtime-async-std-native-tls", "sqlx-postgres", "macros"]

Expand Down
4 changes: 4 additions & 0 deletions frameworks/Rust/trillium/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,3 +53,7 @@ PostgreSQL.
### Test 6: Plaintext

http://localhost:8080/plaintext

### Test 7: Caching

http://localhost:8080/cached/20
2 changes: 2 additions & 0 deletions frameworks/Rust/trillium/benchmark_config.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
"query_url": "/queries/",
"plaintext_url": "/plaintext",
"fortune_url": "/fortunes",
"cached_query_url": "/cached-queries/",
"update_url": "/updates/",
"port": 8080,
"approach": "Realistic",
"classification": "Micro",
Expand Down
8 changes: 2 additions & 6 deletions frameworks/Rust/trillium/src/application.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,10 @@
use crate::db::Db;
use crate::routes::router;
use trillium_logger::Logger;

pub fn application() -> impl trillium::Handler {
(
if cfg!(debug_assertions) {
Some(Logger::new())
} else {
None
},
#[cfg(debug_assertions)]
trillium_logger::logger(),
Db::default(),
router(),
)
Expand Down
25 changes: 15 additions & 10 deletions frameworks/Rust/trillium/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,23 @@ use trillium::{async_trait, Conn, Handler, Info};
#[derive(Debug, Default)]
pub struct Db(Option<DatabaseConnection>);

pub mod cached_world;
pub mod fortune;
pub mod world;

impl Db {
pub(crate) async fn connection() -> DatabaseConnection {
let db_url = env::var("DATABASE_URL").expect("env var DATABASE_URL not found");

let connect_options = ConnectOptions::new(db_url.clone());

Database::connect(connect_options)
.await
.map_err(|e| format!("could not connect to {}: {}", &db_url, e))
.unwrap()
}
}

#[async_trait]
impl Handler for Db {
async fn run(&self, conn: Conn) -> Conn {
Expand All @@ -16,16 +30,7 @@ impl Handler for Db {

async fn init(&mut self, _info: &mut Info) {
if self.0.is_none() {
let db_url = env::var("DATABASE_URL").expect("env var DATABASE_URL not found");

let connect_options = ConnectOptions::new(db_url.clone());

let db = Database::connect(connect_options)
.await
.map_err(|e| format!("could not connect to {}: {}", &db_url, e))
.unwrap();

self.0 = Some(db);
self.0 = Some(Self::connection().await);
}
}
}
Expand Down
24 changes: 24 additions & 0 deletions frameworks/Rust/trillium/src/db/cached_world.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use sea_orm::entity::prelude::*;
use serde::Serialize;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)]
#[sea_orm(table_name = "World")]
#[serde(rename_all = "camelCase")]
pub struct Model {
#[sea_orm(primary_key)]
pub id: i32,

#[sea_orm(column_name = "randomnumber")]
pub random_number: i32,
}

#[derive(Copy, Clone, Debug, EnumIter)]
pub enum Relation {}

impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
unimplemented!()
}
}

impl ActiveModelBehavior for ActiveModel {}
15 changes: 14 additions & 1 deletion frameworks/Rust/trillium/src/db/fortune.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
use sea_orm::entity::prelude::*;
use serde::Serialize;
use std::cmp::Ordering;

#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize)]
#[derive(Clone, Debug, PartialEq, DeriveEntityModel, Serialize, Eq)]
#[sea_orm(table_name = "Fortune")]
pub struct Model {
#[sea_orm(primary_key)]
Expand All @@ -20,3 +21,15 @@ impl RelationTrait for Relation {
}

impl ActiveModelBehavior for ActiveModel {}

impl PartialOrd for Model {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}

impl Ord for Model {
fn cmp(&self, other: &Self) -> Ordering {
self.message.cmp(&other.message)
}
}
14 changes: 12 additions & 2 deletions frameworks/Rust/trillium/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,19 @@
mod application;
mod db;
mod routes;

use application::application;
use trillium::HttpConfig;

fn main() {
trillium_async_std::run(application())
#[cfg(debug_assertions)]
env_logger::init();

let http_config = HttpConfig::default()
.with_response_buffer_len(256)
.with_request_buffer_initial_len(256)
.with_response_header_initial_capacity(5);

trillium_smol::config()
.with_http_config(http_config)
.run(application())
}
5 changes: 4 additions & 1 deletion frameworks/Rust/trillium/src/routes.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use trillium_router::Router;
mod cached_queries;
mod db;
mod fortune;
mod json;
mod plaintext;
mod queries;
mod updates;

pub fn router() -> Router {
Router::build(|mut router| {
router.get("/fortunes", fortune::handler);
Expand All @@ -16,5 +16,8 @@ pub fn router() -> Router {
router.get("/plaintext", plaintext::handler);
router.get("/updates/:updates", updates::handler);
router.get("/updates", updates::handler);
let cached_queries = cached_queries::handler();
router.get("/cached-queries/:count", cached_queries.clone());
router.get("/cached-queries", cached_queries);
})
}
80 changes: 80 additions & 0 deletions frameworks/Rust/trillium/src/routes/cached_queries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use crate::db::{
cached_world::{Entity as CachedWorlds, Model as CachedWorld},
Db, DbConnExt,
};
use futures_lite::StreamExt;
use moka::future::Cache;
use sea_orm::{DatabaseConnection, DbErr, EntityTrait};
use std::{iter, sync::Arc};
use trillium::{Conn, Handler, Info, Status};
use trillium_api::ApiConnExt;
use trillium_router::RouterConnExt;
use unicycle::FuturesUnordered;

pub fn handler() -> CachedWorldHandler {
CachedWorldHandler {
cache: Cache::new(20_000),
}
}

#[derive(Debug, Clone)]
pub struct CachedWorldHandler {
cache: Cache<i32, CachedWorld>,
}

impl CachedWorldHandler {
#[inline(always)]
fn count_param(conn: &Conn) -> usize {
conn.param("count")
.and_then(|s| s.parse().ok())
.unwrap_or(1)
.min(500)
.max(1)
}

#[inline(always)]
async fn fetch_cached(
&self,
db: &DatabaseConnection,
id: i32,
) -> Result<CachedWorld, Arc<DbErr>> {
self.cache
.try_get_with(id, async {
CachedWorlds::find_by_id(id)
.one(db)
.await?
.ok_or_else(|| DbErr::RecordNotFound(String::from("not found")))
})
.await
}
}

#[trillium::async_trait]
impl Handler for CachedWorldHandler {
async fn init(&mut self, _info: &mut Info) {
if self.cache.entry_count() == 0 {
let db = Db::connection().await;
let mut stream = CachedWorlds::find().stream(&db).await.unwrap();
while let Some(Ok(world)) = stream.next().await {
self.cache.insert(world.id, world).await
}
self.cache.run_pending_tasks().await;
}
}

async fn run(&self, conn: Conn) -> Conn {
let count = Self::count_param(&conn);
let db = conn.db();
let worlds: Result<Vec<_>, _> =
iter::repeat_with(|| self.fetch_cached(db, fastrand::i32(1..=10000)))
.take(count)
.collect::<FuturesUnordered<_>>()
.try_collect()
.await;

match worlds {
Ok(worlds) => conn.with_json(&worlds),
Err(_) => conn.with_status(Status::InternalServerError),
}
}
}
19 changes: 7 additions & 12 deletions frameworks/Rust/trillium/src/routes/db.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,13 @@
use crate::db::{world::Entity as World, DbConnExt};
use sea_orm::entity::prelude::*;
use trillium::{conn_unwrap, Conn};
use trillium::{Conn, Status};
use trillium_api::ApiConnExt;

pub async fn handler(conn: Conn) -> Conn {
let random = fastrand::i32(1..10000);
let world = conn_unwrap!(
World::find_by_id(random)
.one(conn.db())
.await
.ok()
.flatten(),
conn
);

conn.with_json(&world)
let id = fastrand::i32(1..10000);
match World::find_by_id(id).one(conn.db()).await {
Ok(Some(world)) => conn.with_json(&world),
Err(_) => conn.with_status(Status::InternalServerError),
Ok(None) => conn.with_status(Status::NotFound),
}
}
22 changes: 15 additions & 7 deletions frameworks/Rust/trillium/src/routes/fortune.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,34 @@ use crate::db::{
fortune::{Entity as Fortunes, Model as Fortune},
DbConnExt,
};
use sea_orm::entity::prelude::*;
use trillium::{conn_try, Conn, KnownHeaderName::ContentType};
use futures_lite::StreamExt;
use sea_orm::EntityTrait;
use std::collections::BTreeSet;
use trillium::{Conn, KnownHeaderName::ContentType, Status};
use trillium_askama::{AskamaConnExt, Template};

#[derive(Template)]
#[template(path = "fortunes.html")]
struct FortuneTemplate<'a> {
fortunes: &'a [Fortune],
fortunes: &'a BTreeSet<Fortune>,
}

pub async fn handler(conn: Conn) -> Conn {
let db = conn.db();
let db = conn.db().clone();

let mut fortunes = conn_try!(Fortunes::find().all(db).await, conn);
fortunes.push(Fortune {
let mut fortunes = BTreeSet::new();
fortunes.insert(Fortune {
id: 0,
message: String::from("Additional fortune added at request time."),
});

fortunes.sort_by(|a, b| a.message.cmp(&b.message));
let Ok(mut stream) = Fortunes::find().stream(&db).await else {
return conn.with_status(Status::InternalServerError);
};

while let Some(Ok(fortune)) = stream.next().await {
fortunes.insert(fortune);
}

conn.render(FortuneTemplate {
fortunes: &fortunes,
Expand Down
9 changes: 4 additions & 5 deletions frameworks/Rust/trillium/src/routes/json.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
use serde_json::{json, to_string};
use trillium::{conn_try, Conn, KnownHeaderName};
use serde_json::json;
use trillium::Conn;
use trillium_api::ApiConnExt;

pub async fn handler(conn: Conn) -> Conn {
let body = conn_try!(to_string(&json!({"message": "Hello, World!"})), conn);
conn.ok(body)
.with_header(KnownHeaderName::ContentType, "application/json")
conn.with_json(&json!({"message": "Hello, World!"}))
}
Loading

0 comments on commit f4513e7

Please sign in to comment.