Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions frameworks/Rust/anansi/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
[workspace]
members = [
".",
]

[package]
name = "tfb-anansi"
version = "0.1.0"
edition = "2021"

[features]
raw = []

[dependencies]
anansi = { git = "https://github.com/saru-tora/anansi", rev = "2567157", features = ["postgres", "minimal", "redis"] }
async-trait = "0.1.57"
rand = "0.8.4"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
36 changes: 36 additions & 0 deletions frameworks/Rust/anansi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# [Anansi](https://saru-tora.github.io/anansi/) Benchmarking Test

Anansi is a simple full-stack web framework for Rust.

### Test Type Implementation Source Code

All tests can be found in: src/hello/world/

## Test URLs
### JSON

http://localhost:8080/json

### PLAINTEXT

http://localhost:8080/plaintext

### DB

http://localhost:8080/db

### QUERY

http://localhost:8080/query?queries=

### CACHED QUERY

http://localhost:8080/cached_query?queries=

### UPDATE

http://localhost:8080/update?queries=

### FORTUNES

http://localhost:8080/fortunes
11 changes: 11 additions & 0 deletions frameworks/Rust/anansi/anansi-raw.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FROM rust:1.64

ADD ./ /anansi
WORKDIR /anansi

RUN cargo clean
RUN RUSTFLAGS="-C target-cpu=native" cargo build --release --features raw

EXPOSE 8080

CMD RUST_LOG=off ./target/release/tfb-anansi 0.0.0.0:8080
14 changes: 14 additions & 0 deletions frameworks/Rust/anansi/anansi.dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM rust:1.64

RUN apt-get update -yqq && apt-get install -yqq --no-install-recommends redis-server

ADD ./ /anansi
WORKDIR /anansi

RUN cargo clean
RUN RUSTFLAGS="-C target-cpu=native" cargo build --release

EXPOSE 8080

ENV RUST_LOG=off
CMD service redis-server start && ./target/release/tfb-anansi 0.0.0.0:8080
52 changes: 52 additions & 0 deletions frameworks/Rust/anansi/benchmark_config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"framework": "anansi",
"tests": [
{
"default": {
"json_url": "/json",
"plaintext_url": "/plaintext",
"db_url": "/db",
"fortune_url": "/fortunes",
"query_url": "/queries?q=",
"update_url": "/updates?q=",
"cached_query_url": "/cached-queries?q=",
"port": 8080,
"approach": "Realistic",
"classification": "Fullstack",
"database": "postgres",
"framework": "Anansi",
"language": "Rust",
"flavor": "None",
"orm": "Full",
"platform": "None",
"webserver": "hyper",
"os": "Linux",
"database_os": "Linux",
"display_name": "Anansi",
"notes": "",
"versus": "None"
},
"raw": {
"db_url": "/db",
"fortune_url": "/fortunes",
"query_url": "/queries?q=",
"update_url": "/updates?q=",
"port": 8080,
"approach": "Realistic",
"classification": "Fullstack",
"database": "postgres",
"framework": "Anansi",
"language": "Rust",
"flavor": "None",
"orm": "Raw",
"platform": "None",
"webserver": "hyper",
"os": "Linux",
"database_os": "Linux",
"display_name": "Anansi [raw]",
"notes": "",
"versus": "None"
}
}
]
}
19 changes: 19 additions & 0 deletions frameworks/Rust/anansi/settings.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
secret_key = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
login_url = "/login"
smtp_relay = ""
smtp_username = ""
smtp_password = ""

[caches]

[caches.default]
location = "redis://127.0.0.1/"

[databases]

[databases.default]
name = "hello_world"
user = "benchmarkdbuser"
password = "benchmarkdbpass"
address = "tfb-database"
max_conn = 512
3 changes: 3 additions & 0 deletions frameworks/Rust/anansi/src/hello/migrations/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use anansi::migrations::prelude::*;

local_migrations! {}
7 changes: 7 additions & 0 deletions frameworks/Rust/anansi/src/hello/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
pub mod urls;
#[cfg(not(feature = "raw"))]
pub mod records;
pub mod migrations;

pub const APP_NAME: &'static str = "hello";
pub mod world;
47 changes: 47 additions & 0 deletions frameworks/Rust/anansi/src/hello/records.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#![allow(non_snake_case)]
use async_trait::async_trait;
use anansi::web::{Result, BaseRequest};
use anansi::record;
use anansi::records::{Relate, Int, Text, random_int};
use serde::Serialize;

#[record(table_name = "World")]
#[derive(Serialize)]
pub struct World {
#[field(primary_key = "true", default_fn = "random_int")]
pub id: Int,
pub randomNumber: Int,
}

#[async_trait]
impl<R: BaseRequest> Relate<R> for World {
async fn on_save(&self, _req: &R) -> Result<()> {
unimplemented!();
}
async fn on_delete(&self, _req: &R) -> Result<()> {
unimplemented!();
}
}

#[record(table_name = "Fortune")]
pub struct Fortune {
#[field(primary_key = "true", default_fn = "random_int")]
pub id: Int,
pub message: Text,
}

impl Fortune {
pub fn additional() -> Self {
Self {id: Int::new(0), message: Text::from("Additional fortune added at request time.".to_string())}
}
}

#[async_trait]
impl<R: BaseRequest> Relate<R> for Fortune {
async fn on_save(&self, _req: &R) -> Result<()> {
unimplemented!();
}
async fn on_delete(&self, _req: &R) -> Result<()> {
unimplemented!();
}
}
3 changes: 3 additions & 0 deletions frameworks/Rust/anansi/src/hello/urls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
use anansi::web::prelude::*;

routes! {}
5 changes: 5 additions & 0 deletions frameworks/Rust/anansi/src/hello/world/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#[cfg(not(feature = "raw"))]
pub mod views;
#[cfg(feature = "raw")]
pub mod raw;
pub mod util;
133 changes: 133 additions & 0 deletions frameworks/Rust/anansi/src/hello/world/raw.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
use crate::prelude::*;
use serde::Serialize;
use anansi::check;
use anansi::db::postgres::{PgDbRow, PgQuery};
use super::util::get_query;
use std::borrow::Cow;
use anansi::db::DbRow;
use rand::Rng;
use std::fmt::Write;

thread_local!(static UPDATES: Vec<Cow<'static, str>> = {
let mut updates = vec![Cow::from("")];
for num in 1..=500u16 {
let mut pl = 1;
let mut q = "UPDATE world SET randomnumber = CASE id ".to_string();
for _ in 1..=num {
let _ = write!(q, "WHEN ${} THEN ${} ", pl, pl + 1);
pl += 2;
}

q.push_str("ELSE randomnumber END WHERE id IN (");

for _ in 1..=num {
let _ = write!(q, "${},", pl);
pl += 1;
}

q.pop();
q.push(')');

updates.push(Cow::from(q));
}
updates
});

fn random_num() -> i32 {
rand::thread_rng().gen_range(1..=10_000)
}

#[derive(Copy, Clone, Serialize, Debug)]
pub struct World {
id: i32,
randomnumber: i32,
}

#[derive(Serialize, Debug)]
pub struct Fortune {
id: i32,
message: Cow<'static, str>,
}

#[base_view]
fn base<R: Request>(_req: &mut R) -> Result<Response> {}

#[viewer]
impl<R: Request> WorldView<R> {
async fn get_world(req: &R) -> Result<PgDbRow> {
PgQuery::new("SELECT * FROM world WHERE id = $1")
.bind(random_num())
.fetch_one(req)
.await
}
async fn get_worlds(req: &R) -> Result<Vec<World>> {
let q = get_query(req.params());
let mut worlds = Vec::with_capacity(q as usize);
for _ in 0..q {
let row = Self::get_world(req).await?;
let world = World {
id: row.try_i32("id")?,
randomnumber: row.try_i32("randomnumber")?,
};
worlds.push(world);
}
Ok(worlds)
}
#[check(Site::is_visitor)]
pub async fn db(req: &mut R) -> Result<Response> {
let row = Self::get_world(req).await?;
let world = World {
id: row.try_i32("id")?,
randomnumber: row.try_i32("randomnumber")?,
};
Response::json(&world)
}
#[check(Site::is_visitor)]
pub async fn queries(req: &mut R) -> Result<Response> {
let worlds = Self::get_worlds(req).await?;
Response::json(&worlds)
}
#[view(Site::is_visitor)]
pub async fn raw_fortunes(req: &mut R) -> Result<Response> {
let title = "Fortunes";
let rows = PgQuery::new("SELECT * FROM fortune")
.fetch_all(req)
.await?;
let mut fortunes = vec![Fortune {
id: 0,
message: Cow::Borrowed("Additional fortune added at request time.")
}];
for row in rows {
fortunes.push(Fortune {
id: row.try_i32("id")?,
message: Cow::Owned(row.try_string("message")?),
})
}
fortunes.sort_by(|it, next| it.message.cmp(&next.message));
}
#[check(Site::is_visitor)]
pub async fn updates(req: &mut R) -> Result<Response> {
let q = get_query(req.params()) as usize;
let mut worlds = Vec::with_capacity(q);
let mut update = Cow::from("");
UPDATES.with(|u| {
update = u[q].clone();
});
let mut updates = PgQuery::new(&update);
for _ in 0..q {
let row = Self::get_world(req).await?;
let world = World {
id: row.try_i32("id")?,
randomnumber: random_num(),
};
updates = updates.bind(world.id)
.bind(world.randomnumber);
worlds.push(world);
}
for world in &worlds {
updates = updates.bind(world.id);
}
updates.execute(req).await?;
Response::json(&worlds)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{let mut _c = String::new();_c.push_str("<!DOCTYPE html>
<html lang=\"en\">
<head>
<title>");_c.push_str(&_base_args._title);_c.push_str("</title>
</head>
<body>
");_c.push_str(&_base_args._content);_c.push_str("
</body>
</html>");Ok(anansi::web::Response::new(200, _c.into_bytes()))}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub struct Args {pub _title: String,pub _content: String,}impl anansi::cache::Cacheable for Args {fn to_bytes(&self) -> Vec<u8> {let mut v = vec![];v.append(&mut self._title.len().to_ne_bytes().to_vec());v.append(&mut self._title.as_bytes().to_vec());v.append(&mut self._content.len().to_ne_bytes().to_vec());v.append(&mut self._content.as_bytes().to_vec());v} fn from_bytes(mut __b: Vec<u8>) -> anansi::web::Result<Self> {let mut buf = __b.split_off(8); let l = usize::from_ne_bytes(__b.try_into().unwrap()); let mut __b = buf.split_off(l); let _title = String::from_utf8(buf)?;let mut buf = __b.split_off(8); let l = usize::from_ne_bytes(__b.try_into().unwrap()); let mut __b = buf.split_off(l); let _content = String::from_utf8(buf)?;Ok(Self {_title, _content, })}} impl Args {pub fn new() -> Self {Self {_title: String::new(), _content: String::new(), }}}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{_args._title = {let mut _c = String::new();_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str(""); _c};_args._content = {let mut _c = String::new();_c.push_str(" <table>
<tr><th>id</th><th>message</th></tr>
");for fortune in fortunes {_c.push_str("
<tr><td>");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.pk())));_c.push_str("</td><td>");_c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message)));_c.push_str("</td></tr>
");}_c.push_str("
</table>"); _c};_args}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{_args._title = {let mut _c = String::new();_c.push_str("");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str(""); _c};_args._content = {let mut _c = String::new();_c.push_str(" <h1>");_c.push_str(&anansi::web::html_escape(&format!("{}", title)));_c.push_str("</h1>"); _c};_args}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{_args._title = {let mut _c = String::new();_c.push_str(&anansi::web::html_escape(&format!("{}", title))); _c};
_args._content = {let mut _c = String::new();_c.push_str("<table><tr><th>id</th><th>message</th></tr>");
for fortune in fortunes {_c.push_str("<tr><td>"); _c.push_str(&anansi::web::html_escape(&format!("{}", fortune.id)));
_c.push_str("</td><td>"); _c.push_str(&anansi::web::html_escape(&format!("{}", fortune.message))); _c.push_str("</td></tr>");
} _c.push_str("</table>"); _c};_args}
Loading