Browse Source

[Rust] Fix the Rocket framework bench (#8742)

* Branch rebase

* Test version increment

* Rust container version fix

* Fixed the UPDATE test

* Keep alive config fix

---------

Co-authored-by: Victor.G <[email protected]>
Nautilus-1021 1 year ago
parent
commit
a0707d746c

+ 3 - 1
frameworks/Rust/rocket/.gitignore

@@ -1 +1,3 @@
-.env
+.env
+
+Cargo.lock

File diff suppressed because it is too large
+ 262 - 299
frameworks/Rust/rocket/Cargo.lock


+ 10 - 22
frameworks/Rust/rocket/Cargo.toml

@@ -1,6 +1,6 @@
 [package]
 name = "rocket_techempower"
-version = "0.4.0"
+version = "0.5.0"
 authors = [
   "Marcelo Barbosa <[email protected]>",
   "Brendan Hansknecht <[email protected]>",
@@ -17,27 +17,15 @@ opt-level = 3
 name = "rocket"
 path = "src/main.rs"
 
-[[bin]]
-name = "rocket-diesel"
-path = "rocket-diesel/main.rs"
+# The Diesel version is broken
+#[[bin]]
+#name = "rocket-diesel"
+#path = "rocket-diesel/main.rs"
 
 [dependencies]
-diesel = { version = "1.4", features = ["postgres"] }
-rocket_sync_db_pools = { version = "0.1.0-rc.2", default-features = false, features = ["diesel_postgres_pool"] }
-rocket_dyn_templates = { version = "0.1.0-rc.2", features = ["handlebars"] }
-serde = { version = "1.0", features = ["derive"] }
-serde_json = "1.0"
-serde_derive = "1.0"
-dotenv = "0.15.0"
-figment = "0.10.6"
+#rocket_sync_db_pools = { version = "0.1.0", default-features = false, features = ["diesel_postgres_pool"] }
 rand = { version = "0.8", features = ["small_rng"] }
-rocket = { version = "0.5.0-rc.2", features = [ "json" ] }
-rocket_db_pools = { version = "0.1.0-rc.2", features = [ "sqlx_postgres" ] }
-sqlx = { version = "0.5.13", features = [ "postgres", "macros" ] }
-yarte = "0.15.6"
-# temp issue https://github.com/SergioBenitez/Rocket/issues/2491
-proc-macro2 = "= 1.0.51"
-async-stream = "0.3.3"
-async-trait = "0.1.53"
-futures = "0.3.21"
-futures-util = "0.3.21"
+rocket = { version = "0.5.0", features = [ "json" ] }
+rocket_db_pools = { version = "0.1.0", features = [ "sqlx_postgres" ] }
+rocket_dyn_templates = { version = "0.1.0", features = ["handlebars"] }
+sqlx = { version = "0.7", features = ["macros"] }

+ 8 - 0
frameworks/Rust/rocket/Rocket.toml

@@ -0,0 +1,8 @@
+[default]
+address = "0.0.0.0"
+port = 8000
+log_level = "off"
+
+[default.databases.hello_world]
+url = "postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world"
+connect_timeout = 5

+ 50 - 49
frameworks/Rust/rocket/benchmark_config.json

@@ -1,53 +1,54 @@
 {
   "framework": "rocket",
   "tests": [{
-      "default": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "fortune_url": "/fortunes",
-        "query_url": "/queries?q=",
-        "update_url": "/updates?q=",
-        "port": 8000,
-        "approach": "Realistic",
-        "classification": "Fullstack",
-        "database": "Postgres",
-        "framework": "Rocket",
-        "language": "Rust",
-        "flavor": "None",
-        "orm": "Full",
-        "platform": "Rust",
-        "webserver": "Hyper",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "Rocket",
-        "notes": "",
-        "versus": "None",
-        "tags": ["broken"]
-      },
-      "diesel": {
-        "json_url": "/json",
-        "plaintext_url": "/plaintext",
-        "db_url": "/db",
-        "fortune_url": "/fortunes",
-        "query_url": "/queries?q=",
-        "update_url": "/updates?q=",
-        "port": 8000,
-        "approach": "Realistic",
-        "classification": "Fullstack",
-        "database": "Postgres",
-        "framework": "Rocket",
-        "language": "Rust",
-        "flavor": "None",
-        "orm": "Full",
-        "platform": "Rust",
-        "webserver": "Hyper",
-        "os": "Linux",
-        "database_os": "Linux",
-        "display_name": "Rocket (Diesel)",
-        "notes": "",
-        "versus": "None",
-        "tags": ["broken"]
-      }
-    }]
+    "default": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "fortune_url": "/fortunes",
+      "query_url": "/queries?q=",
+      "update_url": "/updates?q=",
+      "port": 8000,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "Rocket",
+      "language": "Rust",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Rust",
+      "webserver": "Hyper",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Rocket",
+      "notes": "",
+      "versus": "None"
+    },
+    "diesel": {
+      "json_url": "/json",
+      "plaintext_url": "/plaintext",
+      "db_url": "/db",
+      "fortune_url": "/fortunes",
+      "query_url": "/queries?q=",
+      "update_url": "/updates?q=",
+      "port": 8000,
+      "approach": "Realistic",
+      "classification": "Fullstack",
+      "database": "Postgres",
+      "framework": "Rocket",
+      "language": "Rust",
+      "flavor": "None",
+      "orm": "Full",
+      "platform": "Rust",
+      "webserver": "Hyper",
+      "os": "Linux",
+      "database_os": "Linux",
+      "display_name": "Rocket (Diesel)",
+      "notes": "",
+      "versus": "None",
+      "tags": [
+        "broken"
+      ]
+    }
+  }]
 }

+ 1 - 1
frameworks/Rust/rocket/rocket-diesel.dockerfile

@@ -1,4 +1,4 @@
-FROM rust:1.63
+FROM rust:1.76-slim
 
 ENV ROCKET_BENCHMARK_DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world
 

+ 1 - 7
frameworks/Rust/rocket/rocket.dockerfile

@@ -1,10 +1,4 @@
-FROM rust:1.60-slim
-
-ENV ROCKET_BENCHMARK_DATABASE_URL=postgres://benchmarkdbuser:benchmarkdbpass@tfb-database/hello_world
-
-RUN apt-get update && apt-get install -y --no-install-recommends \
-    libpq-dev \
-&& rm -rf /var/lib/apt/lists/*
+FROM rust:1.76
 
 ADD ./ /rocket
 WORKDIR /rocket

+ 0 - 2
frameworks/Rust/rocket/rust-toolchain.toml

@@ -1,2 +0,0 @@
-[toolchain]
-channel = "stable"

+ 67 - 104
frameworks/Rust/rocket/src/main.rs

@@ -1,24 +1,14 @@
-#[macro_use]
-extern crate rocket;
-extern crate dotenv;
-extern crate serde_derive;
-
 mod database;
 mod models;
 
-use std::env;
-use std::net::{IpAddr, Ipv4Addr};
+use std::fmt::Write;
 
-use dotenv::dotenv;
-use figment::Figment;
 use rand::{self, Rng};
-use rocket::{Build, Rocket};
-use rocket::config::{Config, LogLevel};
-use rocket::response::content::RawHtml;
+use rocket::{launch, get, routes};
 use rocket::serde::json::Json;
-use rocket_db_pools::{sqlx, Connection, Database};
-use sqlx::Acquire;
-use yarte::Template;
+use rocket_db_pools::{Connection, Database};
+use rocket_db_pools::sqlx;
+use rocket_dyn_templates::{Template, context};
 
 use database::HelloWorld;
 use models::{Fortune, Message, World};
@@ -28,12 +18,11 @@ fn plaintext() -> &'static str {
     "Hello, World!"
 }
 
+const MESSAGE: Message = Message { message: "Hello, World!" };
+
 #[get("/json")]
 fn json() -> Json<models::Message> {
-    let message = Message {
-        message: "Hello, World!".into(),
-    };
-    Json(message)
+    Json(MESSAGE)
 }
 
 fn random_id() -> i32 {
@@ -42,16 +31,18 @@ fn random_id() -> i32 {
     rng.gen_range(1..=10_000)
 }
 
+async fn query_random_world(db: &mut Connection<HelloWorld>) -> World {
+    let world_id = random_id();
+    sqlx::query_as("SELECT id, randomnumber FROM World WHERE id = $1")
+        .bind(world_id)
+        .fetch_one(db.as_mut())
+        .await
+        .expect("Error querying world")
+}
+
 #[get("/db")]
 async fn db(mut db: Connection<HelloWorld>) -> Json<World> {
-    let number = random_id();
-    let result: World = sqlx::query_as("SELECT id, randomnumber FROM World WHERE id = $1")
-        .bind(number)
-        .fetch_one(&mut *db)
-        .await
-        .ok()
-        .expect("error loading world");
-    Json(result)
+    Json(query_random_world(&mut db).await)
 }
 
 #[get("/queries")]
@@ -65,31 +56,19 @@ async fn queries(mut db: Connection<HelloWorld>, q: u16) -> Json<Vec<World>> {
     let mut results = Vec::with_capacity(q.into());
 
     for _ in 0..q {
-        let query_id = random_id();
-        let result: World = sqlx::query_as("SELECT * FROM World WHERE id = $1")
-            .bind(query_id)
-            .fetch_one(&mut *db)
-            .await
-            .ok()
-            .expect("error loading world");
-        results.push(result);
+        let world = query_random_world(&mut db).await;
+
+        results.push(world);
     }
 
     Json(results)
 }
 
-#[derive(Template)]
-#[template(path = "fortunes.html.hbs")]
-pub struct FortunesTemplate<'a> {
-    pub fortunes: &'a Vec<Fortune>,
-}
-
 #[get("/fortunes")]
-async fn fortunes(mut db: Connection<HelloWorld>) -> RawHtml<String> {
+async fn fortunes(mut db: Connection<HelloWorld>) -> Template {
     let mut fortunes: Vec<Fortune> = sqlx::query_as("SELECT * FROM Fortune")
-        .fetch_all(&mut *db)
+        .fetch_all(db.as_mut())
         .await
-        .ok()
         .expect("Could not load Fortunes");
 
     fortunes.push(Fortune {
@@ -99,13 +78,9 @@ async fn fortunes(mut db: Connection<HelloWorld>) -> RawHtml<String> {
 
     fortunes.sort_by(|a, b| a.message.cmp(&b.message));
 
-    RawHtml(
-        FortunesTemplate {
-            fortunes: &fortunes,
-        }
-        .call()
-        .expect("error rendering template"),
-    )
+    Template::render("fortunes", context! {
+        fortunes: fortunes
+    })
 }
 
 #[get("/updates")]
@@ -119,70 +94,57 @@ async fn updates(mut db: Connection<HelloWorld>, q: u16) -> Json<Vec<World>> {
     let mut results = Vec::with_capacity(q.into());
 
     for _ in 0..q {
-        let query_id = random_id();
-        let mut result: World = sqlx::query_as("SELECT * FROM World WHERE id = $1")
-            .bind(query_id)
-            .fetch_one(&mut *db)
-            .await
-            .ok()
-            .expect("World was not found");
-
-        result.random_number = random_id();
-        results.push(result);
+        let mut world = query_random_world(&mut db).await;
+
+        world.random_number = random_id();
+        results.push(world);
     }
 
-    let mut pool = db.into_inner();
-    let mut tx = pool
-        .begin()
-        .await
-        .ok()
-        .expect("could not start transaction");
+    let query_string = {
+        let mut query = String::new();
+
+        query.push_str("UPDATE World SET randomnumber = CASE id ");
+
+        let mut pl = 1;
+
+        for _ in 1..=q {
+            let _ = write!(query, "when ${pl} then ${} ", pl + 1);
+            pl += 2;
+        }
+
+        query.push_str("ELSE randomnumber END WHERE id IN (");
+
+        for _ in 1..=q {
+            let _ = write!(query, "${pl},");
+            pl += 1;
+        }
+
+        query.pop();
+        query.push(')');
+
+        query
+    };
+
+    let mut query = sqlx::query(&query_string);
 
     for w in &results {
-        sqlx::query("UPDATE World SET randomnumber = $1 WHERE id = $2")
-            .bind(w.random_number)
-            .bind(w.id)
-            .execute(&mut tx)
-            .await
-            .ok()
-            .expect("Could not update World");
+        query = query.bind(w.id).bind(w.random_number);
     }
 
-    tx.commit().await.ok().expect("could not update worlds");
+    for w in &results {
+        query = query.bind(w.id);
+    }
+
+    query.execute(db.as_mut())
+        .await
+        .expect("Could not update worlds");
 
     Json(results)
 }
 
 #[launch]
-pub fn launch() -> Rocket<Build> {
-    if cfg!(not(test)) {
-        dotenv().ok();
-    }
-
-    let config = Config {
-        address: IpAddr::V4(Ipv4Addr::new(0, 0, 0, 0)),
-        port: 8000,
-        keep_alive: 0,
-        log_level: LogLevel::Off,
-        ..Default::default()
-    };
-
-    let database_url = env::var("ROCKET_BENCHMARK_DATABASE_URL")
-        .ok()
-        .expect("ROCKET_BENCHMARK_DATABASE_URL environment variable was not set");
-
-    let figment = Figment::from(config).merge((
-        "databases.hello_world",
-        rocket_db_pools::Config {
-            url: database_url,
-            min_connections: None,
-            max_connections: 100,
-            connect_timeout: 3,
-            idle_timeout: None,
-        },
-    ));
-
-    rocket::custom(figment)
+pub fn launch() -> _ {
+    rocket::build()
         .mount(
             "/",
             routes![
@@ -197,4 +159,5 @@ pub fn launch() -> Rocket<Build> {
             ],
         )
         .attach(HelloWorld::init())
+        .attach(Template::fairing())
 }

+ 3 - 5
frameworks/Rust/rocket/src/models.rs

@@ -1,13 +1,12 @@
 use rocket::serde::{Deserialize, Serialize};
-use sqlx::FromRow;
-use std::borrow::Cow;
+use rocket_db_pools::sqlx::FromRow;
 
 #[derive(Serialize)]
+#[serde(crate = "rocket::serde")]
 pub struct Message {
-    pub message: Cow<'static, str>,
+    pub message: &'static str,
 }
 
-#[allow(non_snake_case)]
 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, FromRow)]
 #[serde(crate = "rocket::serde")]
 pub struct Fortune {
@@ -15,7 +14,6 @@ pub struct Fortune {
     pub message: String,
 }
 
-#[allow(non_snake_case)]
 #[derive(Clone, Debug, PartialEq, Deserialize, Serialize, FromRow)]
 #[serde(crate = "rocket::serde")]
 pub struct World {

Some files were not shown because too many files changed in this diff