| #![feature(test)] |
| #![allow(non_snake_case)] |
| #![recursion_limit = "128"] |
| |
| #[macro_use] |
| extern crate diesel; |
| #[macro_use] |
| extern crate diesel_infer_schema; |
| #[cfg(feature = "sqlite")] |
| #[macro_use] |
| extern crate diesel_migrations; |
| extern crate dotenv; |
| extern crate test; |
| |
| mod schema; |
| |
| use self::schema::{ |
| comments, posts, users, Comment, NewComment, NewPost, NewUser, Post, TestConnection, User, |
| }; |
| use self::test::Bencher; |
| use diesel::*; |
| |
| #[cfg(not(feature = "sqlite"))] |
| fn connection() -> TestConnection { |
| let conn = schema::connection(); |
| conn.execute("TRUNCATE TABLE users").unwrap(); |
| conn.execute("TRUNCATE TABLE posts").unwrap(); |
| conn.execute("TRUNCATE TABLE comments").unwrap(); |
| conn |
| } |
| |
| #[cfg(feature = "sqlite")] |
| fn connection() -> TestConnection { |
| schema::connection() |
| } |
| |
| macro_rules! bench_trivial_query { |
| ($n:expr, $name:ident, $name_boxed:ident) => { |
| #[bench] |
| fn $name(b: &mut Bencher) { |
| let conn = connection(); |
| |
| let data: Vec<_> = (0..$n) |
| .map(|i| NewUser::new(&format!("User {}", i), None)) |
| .collect(); |
| insert_into(users::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| |
| b.iter(|| users::table.load::<User>(&conn).unwrap()) |
| } |
| |
| #[bench] |
| fn $name_boxed(b: &mut Bencher) { |
| let conn = connection(); |
| |
| let data: Vec<_> = (0..$n) |
| .map(|i| NewUser::new(&format!("User {}", i), None)) |
| .collect(); |
| insert_into(users::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| |
| b.iter(|| users::table.into_boxed().load::<User>(&conn).unwrap()) |
| } |
| }; |
| } |
| |
| // bench_trivial_query!(0, |
| // bench_trivial_query_selecting______0_rows, bench_trivial_query_selecting______0_rows_boxed); |
| bench_trivial_query!( |
| 1, |
| bench_trivial_query_selecting______1_row, |
| bench_trivial_query_selecting______1_row_boxed |
| ); |
| bench_trivial_query!( |
| 10, |
| bench_trivial_query_selecting_____10_rows, |
| bench_trivial_query_selecting_____10_rows_boxed |
| ); |
| bench_trivial_query!( |
| 100, |
| bench_trivial_query_selecting____100_rows, |
| bench_trivial_query_selecting____100_rows_boxed |
| ); |
| bench_trivial_query!( |
| 1_000, |
| bench_trivial_query_selecting__1_000_rows, |
| bench_trivial_query_selecting__1_000_rows_boxed |
| ); |
| bench_trivial_query!( |
| 10_000, |
| bench_trivial_query_selecting_10_000_rows, |
| bench_trivial_query_selecting_10_000_rows_boxed |
| ); |
| |
| macro_rules! bench_medium_complex_query { |
| ($n:expr, $name:ident, $name_boxed:ident) => { |
| #[bench] |
| fn $name(b: &mut Bencher) { |
| let conn = connection(); |
| |
| let data: Vec<_> = (0..$n) |
| .map(|i| { |
| let hair_color = if i % 2 == 0 { "black" } else { "brown" }; |
| NewUser::new(&format!("User {}", i), Some(hair_color)) |
| }) |
| .collect(); |
| insert_into(users::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| |
| b.iter(|| { |
| use crate::schema::users::dsl::*; |
| let target = users |
| .left_outer_join(posts::table) |
| .filter(hair_color.eq("black")) |
| .order(name.desc()); |
| target.load::<(User, Option<Post>)>(&conn).unwrap() |
| }) |
| } |
| |
| #[bench] |
| fn $name_boxed(b: &mut Bencher) { |
| let conn = connection(); |
| |
| let data: Vec<_> = (0..$n) |
| .map(|i| { |
| let hair_color = if i % 2 == 0 { "black" } else { "brown" }; |
| NewUser::new(&format!("User {}", i), Some(hair_color)) |
| }) |
| .collect(); |
| insert_into(users::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| |
| b.iter(|| { |
| use crate::schema::users::dsl::*; |
| let target = users |
| .left_outer_join(posts::table) |
| .filter(hair_color.eq("black")) |
| .order(name.desc()) |
| .into_boxed(); |
| target.load::<(User, Option<Post>)>(&conn).unwrap() |
| }) |
| } |
| }; |
| } |
| |
| // bench_medium_complex_query!(0, |
| // bench_medium_complex_query_selecting______0_rows, bench_medium_complex_query_selecting______0_rows_boxed); |
| bench_medium_complex_query!( |
| 1, |
| bench_medium_complex_query_selecting______1_row, |
| bench_medium_complex_query_selecting______1_row_boxed |
| ); |
| bench_medium_complex_query!( |
| 10, |
| bench_medium_complex_query_selecting_____10_rows, |
| bench_medium_complex_query_selecting_____10_rows_boxed |
| ); |
| bench_medium_complex_query!( |
| 100, |
| bench_medium_complex_query_selecting____100_rows, |
| bench_medium_complex_query_selecting____100_rows_boxed |
| ); |
| bench_medium_complex_query!( |
| 1_000, |
| bench_medium_complex_query_selecting__1_000_rows, |
| bench_medium_complex_query_selecting__1_000_rows_boxed |
| ); |
| bench_medium_complex_query!( |
| 10_000, |
| bench_medium_complex_query_selecting_10_000_rows, |
| bench_medium_complex_query_selecting_10_000_rows_boxed |
| ); |
| |
| #[bench] |
| fn loading_associations_sequentially(b: &mut Bencher) { |
| // SETUP A TON OF DATA |
| let conn = connection(); |
| let data: Vec<_> = (0..100) |
| .map(|i| { |
| let hair_color = if i % 2 == 0 { "black" } else { "brown" }; |
| NewUser::new(&format!("User {}", i), Some(hair_color)) |
| }) |
| .collect(); |
| insert_into(users::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| let all_users = users::table.load::<User>(&conn).unwrap(); |
| let data: Vec<_> = all_users |
| .iter() |
| .flat_map(|user| { |
| let user_id = user.id; |
| (0..10).map(move |i| { |
| let title = format!("Post {} by user {}", i, user_id); |
| NewPost::new(user_id, &title, None) |
| }) |
| }) |
| .collect(); |
| insert_into(posts::table) |
| .values(&data) |
| .execute(&conn) |
| .unwrap(); |
| let all_posts = posts::table.load::<Post>(&conn).unwrap(); |
| let data: Vec<_> = all_posts |
| .iter() |
| .flat_map(|post| { |
| let post_id = post.id; |
| (0..10).map(move |i| { |
| let title = format!("Comment {} on post {}", i, post_id); |
| (title, post_id) |
| }) |
| }) |
| .collect(); |
| let comment_data: Vec<_> = data |
| .iter() |
| .map(|&(ref title, post_id)| NewComment(post_id, &title)) |
| .collect(); |
| insert_into(comments::table) |
| .values(&comment_data) |
| .execute(&conn) |
| .unwrap(); |
| |
| // ACTUAL BENCHMARK |
| b.iter(|| { |
| let users = users::table.load::<User>(&conn).unwrap(); |
| let posts = Post::belonging_to(&users).load::<Post>(&conn).unwrap(); |
| let comments = Comment::belonging_to(&posts) |
| .load::<Comment>(&conn) |
| .unwrap() |
| .grouped_by(&posts); |
| let posts_and_comments = posts.into_iter().zip(comments).grouped_by(&users); |
| let _result: Vec<(User, Vec<(Post, Vec<Comment>)>)> = |
| users.into_iter().zip(posts_and_comments).collect(); |
| }) |
| } |