kermit_bench/benchmarks/
oxford.rs1use {
2 crate::{
3 benchmark::{Benchmark, BenchmarkMetadata, Task},
4 downloader::{DownloadMethod, DownloadSpec},
5 utils,
6 },
7 std::path::Path,
8};
9
10pub struct OxfordBenchmark;
11
12static METADATA: BenchmarkMetadata = BenchmarkMetadata {
13 name: "Oxford Dataset",
14 description: "Oxford Database Systems and Implementation final course exam",
15 download_spec: DownloadSpec {
16 name: "oxford_dataset",
17 method: DownloadMethod::CLONE,
18 url: "https://github.com/schroederdewitt/leapfrog-triejoin",
19 },
20 tasks: &[
21 Task {
22 name: "Uniform",
23 description: "Uniformly distributed data",
24 location: "dataset1-uniform",
25 },
26 Task {
27 name: "Zipf",
28 description: "Zipf distributed data",
29 location: "dataset2-zipf",
30 },
31 ],
32};
33
34fn translate_dataset(source: &Path, dest: &Path) {
35 let header_path = source.join("databasefile");
37 let headers: Vec<String> = std::fs::read_to_string(&header_path)
38 .unwrap()
39 .lines()
40 .map(|s| s.to_string())
41 .collect();
42
43 for header in headers {
44 let header_content: Vec<String> = header.split(",").map(|s| s.trim().to_string()).collect();
45
46 let rel_file_name = &header_content[0];
47 let rel_name = &header_content[1];
48 let rel_attrs: Vec<String> = header_content[2..]
49 .iter()
50 .map(|s| s.trim().to_string())
51 .filter(|s| !s.is_empty())
52 .collect();
53
54 let data_path = source.join(rel_file_name);
55
56 let data_content: Vec<Vec<usize>> = std::fs::read_to_string(data_path)
57 .unwrap()
58 .trim()
59 .lines()
60 .map(|line| {
61 line.split(",")
62 .take(rel_attrs.len())
63 .map(|s| s.trim().parse::<usize>().unwrap())
64 .collect()
65 })
66 .collect();
67
68 utils::write_relation_to_parquet(
69 &dest.join(format!("{}.parquet", rel_name)),
70 &rel_attrs,
71 &data_content,
72 )
73 .unwrap();
74 }
75}
76
77fn translate_query(source: &Path, dest: &Path) {
78 let query_content: Vec<_> = std::fs::read_to_string(source)
79 .unwrap()
80 .lines()
81 .map(|s| s.to_string())
82 .collect();
83 let rels = query_content[0]
84 .split(",")
85 .filter(|s| !s.is_empty())
86 .map(|s| s.trim())
87 .collect::<Vec<_>>();
88 let attrs = query_content[1]
89 .split(",")
90 .filter(|s| !s.is_empty())
91 .map(|s| s.trim())
92 .collect::<Vec<_>>();
93 let mut file = std::fs::File::create(dest).unwrap();
95 use std::io::Write;
96 writeln!(file, "{}", rels.join(",")).unwrap();
97 writeln!(file, "{}", attrs.join(",")).unwrap();
98}
99
100impl Benchmark for OxfordBenchmark {
101 fn metadata(&self) -> &BenchmarkMetadata { &METADATA }
102
103 fn load(&self, source: &Path, path: &Path) -> Result<(), Box<dyn std::error::Error>> {
104 let dl_spec = &self.metadata().download_spec;
105 let data_dest = path.join(dl_spec.name).join("data");
106 let ds_tmp_path = source.join("datasets");
107 for dataset_parent in ["dataset1-uniform", "dataset2-zipf"] {
108 for dataset_sub in ["scale1", "scale2", "scale3", "scale4", "scale5", "scale6"] {
109 let source_path = ds_tmp_path.join(dataset_parent).join(dataset_sub);
110 let dest_path = data_dest.join(dataset_parent).join(dataset_sub);
111 if !dest_path.exists() {
112 std::fs::create_dir_all(&dest_path)?;
113 }
114 translate_dataset(&source_path, &dest_path);
115 }
116 }
117 let queries_dest = path.join(dl_spec.name).join("queries");
118 if !queries_dest.exists() {
119 std::fs::create_dir_all(&queries_dest)?;
120 }
121 for query_file in ["query1", "query2", "query3"] {
122 let source_path = ds_tmp_path.join(query_file);
123 let dest_path = queries_dest.join(format!("{}.txt", query_file));
124 translate_query(&source_path, &dest_path);
125 }
126 Ok(())
127 }
128}