movie_scanner.rs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. use criterion::{criterion_group, criterion_main, Criterion};
  2. use dim_database::get_conn_file;
  3. use dim_database::library::InsertableLibrary;
  4. use dim_database::library::Library;
  5. use dim_database::library::MediaType;
  6. use tokio::runtime;
  7. use std::fs::hard_link;
  8. use std::fs::File;
  9. use std::path::PathBuf;
  10. use std::time::Duration;
  11. use std::time::Instant;
  12. const TEST_MP4_PATH: &str = concat!(
  13. env!("CARGO_MANIFEST_DIR"),
  14. "/src/scanner/tests/data/test.mp4"
  15. );
  16. fn generate_tag() -> String {
  17. use rand::Rng;
  18. const CHARSET: &[u8] = b"abcdef0123456789";
  19. let mut rng = rand::thread_rng();
  20. (0..8)
  21. .map(|_| {
  22. let idx = rng.gen_range(0..CHARSET.len());
  23. CHARSET[idx] as char
  24. })
  25. .collect()
  26. }
  27. pub fn temp_dir<'a>(files: impl IntoIterator<Item = &'a str>) {
  28. let tempdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR"));
  29. for file in files.into_iter() {
  30. let file_path = tempdir.as_path().join(file);
  31. if let Some(parent) = file_path.parent() {
  32. std::fs::create_dir_all(parent).expect("Failed to create parent dir");
  33. }
  34. let _ = File::create(file_path);
  35. }
  36. }
  37. pub fn temp_dir_symlink<'a>(
  38. files: impl Iterator<Item = impl AsRef<str>>,
  39. target_file: &'a str,
  40. ) -> Vec<PathBuf> {
  41. let tempdir = PathBuf::from(env!("CARGO_TARGET_TMPDIR"));
  42. let mut absolute = vec![];
  43. for file in files.into_iter() {
  44. let file_path = tempdir.as_path().join(file.as_ref());
  45. if let Some(parent) = file_path.parent() {
  46. std::fs::create_dir_all(parent).expect("Failed to create parent dir");
  47. }
  48. let _ = hard_link(target_file, &file_path);
  49. absolute.push(file_path);
  50. }
  51. absolute
  52. }
  53. async fn bootstrap() -> dim_database::DbConnection {
  54. let files = (0..128)
  55. .map(|i| format!("Movie{i}.mkv"))
  56. .collect::<Vec<String>>();
  57. let _files = temp_dir_symlink(files.into_iter(), TEST_MP4_PATH);
  58. let outdir = env!("CARGO_TARGET_TMPDIR");
  59. let tag = generate_tag();
  60. let conn = get_conn_file(&format!("{outdir}/dim.{tag}.db"))
  61. .await
  62. .unwrap();
  63. conn
  64. }
  65. async fn create_library(conn: &mut dim_database::DbConnection) -> i64 {
  66. let mut lock = conn.writer().lock_owned().await;
  67. let mut tx = dim_database::write_tx(&mut lock).await.unwrap();
  68. let id = InsertableLibrary {
  69. name: "Tests".to_string(),
  70. locations: vec![],
  71. media_type: MediaType::Movie,
  72. }
  73. .insert(&mut tx)
  74. .await
  75. .expect("Failed to create test library.");
  76. tx.commit().await.expect("Failed to commit test library.");
  77. id
  78. }
  79. async fn delete_library(conn: &mut dim_database::DbConnection, id: i64) {
  80. let mut lock = conn.writer().lock_owned().await;
  81. let mut tx = dim_database::write_tx(&mut lock).await.unwrap();
  82. Library::delete(&mut tx, id).await.unwrap();
  83. tx.commit().await.expect("Failed to commit test library.");
  84. }
  85. fn movie_scanner_bench(c: &mut Criterion) {
  86. c.bench_function("Scan 128 files", move |b| {
  87. let rt = runtime::Builder::new_multi_thread()
  88. .worker_threads(8)
  89. .enable_all()
  90. .build()
  91. .unwrap();
  92. b.to_async(rt).iter_custom(|iters| async move {
  93. let _path = env!("CARGO_TARGET_TMPDIR").to_string();
  94. let mut db = bootstrap().await;
  95. let mut total_elapsed = Duration::ZERO;
  96. for _ in 0..iters {
  97. let library_id = create_library(&mut db).await;
  98. let start = Instant::now();
  99. // scan_directory(&mut db, library_id, vec![path.clone()]).await;
  100. total_elapsed += start.elapsed();
  101. delete_library(&mut db, library_id).await;
  102. }
  103. total_elapsed
  104. })
  105. });
  106. }
  107. criterion_group!(benches, movie_scanner_bench);
  108. criterion_main!(benches);