gqlite 1.2.0 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/ext/gqliterb/.cargo/config.toml +2 -0
- data/ext/gqliterb/Cargo.lock +152 -135
- data/ext/gqliterb/Cargo.toml +4 -6
- data/ext/gqliterb/src/lib.rs +8 -2
- data/ext/gqliterb/vendor/gqlitedb/Cargo.lock +2115 -0
- data/ext/gqliterb/vendor/gqlitedb/Cargo.toml +138 -0
- data/ext/gqliterb/vendor/gqlitedb/askama.toml +3 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/mod.rs +25 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/common/pokec.rs +185 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_divan.rs +137 -0
- data/ext/gqliterb/vendor/gqlitedb/benches/pokec_iai.rs +122 -0
- data/ext/gqliterb/vendor/gqlitedb/release.toml +7 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/arithmetic.rs +96 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/containers.rs +33 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/count.rs +35 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators/stats.rs +168 -0
- data/ext/gqliterb/vendor/gqlitedb/src/aggregators.rs +74 -0
- data/ext/gqliterb/vendor/gqlitedb/src/capi.rs +259 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/expression_analyser.rs +431 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler/variables_manager.rs +621 -0
- data/ext/gqliterb/vendor/gqlitedb/src/compiler.rs +1115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/connection.rs +342 -0
- data/ext/gqliterb/vendor/gqlitedb/src/consts.rs +10 -0
- data/ext/gqliterb/vendor/gqlitedb/src/error.rs +613 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/containers.rs +115 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/edge.rs +20 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/math.rs +44 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/node.rs +16 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/path.rs +80 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/scalar.rs +86 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/string.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions/value.rs +99 -0
- data/ext/gqliterb/vendor/gqlitedb/src/functions.rs +410 -0
- data/ext/gqliterb/vendor/gqlitedb/src/graph.rs +283 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/evaluators.rs +1776 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/instructions.rs +267 -0
- data/ext/gqliterb/vendor/gqlitedb/src/interpreter/mod.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/lib.rs +41 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/ast.rs +611 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/gql.pest +196 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser/parser.rs +1183 -0
- data/ext/gqliterb/vendor/gqlitedb/src/parser.rs +4 -0
- data/ext/gqliterb/vendor/gqlitedb/src/prelude.rs +8 -0
- data/ext/gqliterb/vendor/gqlitedb/src/serialize_with.rs +94 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/pgql.rs +121 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/redb.rs +1262 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store/sqlite.rs +1026 -0
- data/ext/gqliterb/vendor/gqlitedb/src/store.rs +439 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/compiler.rs +92 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/evaluators.rs +227 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/parser.rs +81 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/redb.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store/sqlite.rs +46 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/store.rs +470 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/ast.rs +356 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates/programs.rs +455 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests/templates.rs +2 -0
- data/ext/gqliterb/vendor/gqlitedb/src/tests.rs +39 -0
- data/ext/gqliterb/vendor/gqlitedb/src/utils.rs +28 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/compare.rs +212 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/contains.rs +47 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value/value_map.rs +298 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value.rs +609 -0
- data/ext/gqliterb/vendor/gqlitedb/src/value_table.rs +610 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/call_stats.sql +22 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_count_for_node.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_create.sql +6 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_delete_by_nodes.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_select.sql +139 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/edge_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_create.sql +16 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/graph_delete.sql +3 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_create_table.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_get.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/metadata_set.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_create.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_delete.sql +1 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_select.sql +42 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/node_update.sql +4 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/table_exists.sql +5 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_from_1_01.sql +2 -0
- data/ext/gqliterb/vendor/gqlitedb/templates/sql/sqlite/upgrade_graph_from_1_01.sql +65 -0
- metadata +82 -2
@@ -0,0 +1,138 @@
|
|
1
|
+
# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO
|
2
|
+
#
|
3
|
+
# When uploading crates to the registry Cargo will automatically
|
4
|
+
# "normalize" Cargo.toml files for maximal compatibility
|
5
|
+
# with all versions of Cargo and also rewrite `path` dependencies
|
6
|
+
# to registry (e.g., crates.io) dependencies.
|
7
|
+
#
|
8
|
+
# If you are reading this file be aware that the original Cargo.toml
|
9
|
+
# will likely look very different (and much more reasonable).
|
10
|
+
# See Cargo.toml.orig for the original contents.
|
11
|
+
|
12
|
+
[package]
|
13
|
+
edition = "2021"
|
14
|
+
name = "gqlitedb"
|
15
|
+
version = "0.5.3"
|
16
|
+
build = false
|
17
|
+
autolib = false
|
18
|
+
autobins = false
|
19
|
+
autoexamples = false
|
20
|
+
autotests = false
|
21
|
+
autobenches = false
|
22
|
+
description = "GQLite is a Rust-language library, with a C interface, that implements a small, fast, self-contained, high-reliability, full-featured, Graph Query database engine."
|
23
|
+
homepage = "https://gqlite.org"
|
24
|
+
readme = "README.md"
|
25
|
+
license = "MIT"
|
26
|
+
repository = "https://gitlab.com/gqlite/gqlite"
|
27
|
+
|
28
|
+
[features]
|
29
|
+
_backtrace = []
|
30
|
+
_pg13 = ["pgrx/pg13"]
|
31
|
+
_pg14 = ["pgrx/pg14"]
|
32
|
+
_pg15 = ["pgrx/pg15"]
|
33
|
+
_pg16 = ["pgrx/pg16"]
|
34
|
+
_pg17 = ["pgrx/pg17"]
|
35
|
+
_pgql = ["dep:pgrx"]
|
36
|
+
_value_private = []
|
37
|
+
capi = []
|
38
|
+
default = [
|
39
|
+
"redb",
|
40
|
+
"capi",
|
41
|
+
"sqlite",
|
42
|
+
]
|
43
|
+
redb = ["dep:redb"]
|
44
|
+
sqlite = [
|
45
|
+
"dep:rusqlite",
|
46
|
+
"dep:askama",
|
47
|
+
]
|
48
|
+
|
49
|
+
[lib]
|
50
|
+
name = "gqlitedb"
|
51
|
+
crate-type = [
|
52
|
+
"cdylib",
|
53
|
+
"lib",
|
54
|
+
]
|
55
|
+
path = "src/lib.rs"
|
56
|
+
|
57
|
+
[[bench]]
|
58
|
+
name = "pokec_divan"
|
59
|
+
path = "benches/pokec_divan.rs"
|
60
|
+
harness = false
|
61
|
+
|
62
|
+
[[bench]]
|
63
|
+
name = "pokec_iai"
|
64
|
+
path = "benches/pokec_iai.rs"
|
65
|
+
harness = false
|
66
|
+
|
67
|
+
[dependencies.askama]
|
68
|
+
version = "0.14"
|
69
|
+
optional = true
|
70
|
+
|
71
|
+
[dependencies.ccutils]
|
72
|
+
version = "0.3"
|
73
|
+
features = [
|
74
|
+
"sync",
|
75
|
+
"pool",
|
76
|
+
]
|
77
|
+
|
78
|
+
[dependencies.ciborium]
|
79
|
+
version = "0.2"
|
80
|
+
|
81
|
+
[dependencies.itertools]
|
82
|
+
version = "0.14"
|
83
|
+
|
84
|
+
[dependencies.pest]
|
85
|
+
version = "2"
|
86
|
+
|
87
|
+
[dependencies.pest_derive]
|
88
|
+
version = "2"
|
89
|
+
|
90
|
+
[dependencies.pgrx]
|
91
|
+
version = "0.15"
|
92
|
+
optional = true
|
93
|
+
|
94
|
+
[dependencies.rand]
|
95
|
+
version = "0.9"
|
96
|
+
|
97
|
+
[dependencies.redb]
|
98
|
+
version = "2"
|
99
|
+
optional = true
|
100
|
+
|
101
|
+
[dependencies.rusqlite]
|
102
|
+
version = "0.37"
|
103
|
+
features = [
|
104
|
+
"functions",
|
105
|
+
"uuid",
|
106
|
+
]
|
107
|
+
optional = true
|
108
|
+
package = "rusqlite"
|
109
|
+
|
110
|
+
[dependencies.serde]
|
111
|
+
version = "1"
|
112
|
+
|
113
|
+
[dependencies.serde_json]
|
114
|
+
version = "1"
|
115
|
+
|
116
|
+
[dependencies.thiserror]
|
117
|
+
version = "2"
|
118
|
+
|
119
|
+
[dependencies.uuid]
|
120
|
+
version = "1"
|
121
|
+
features = ["v4"]
|
122
|
+
|
123
|
+
[dev-dependencies.ccutils]
|
124
|
+
version = "0.3"
|
125
|
+
features = ["temporary"]
|
126
|
+
|
127
|
+
[dev-dependencies.divan]
|
128
|
+
version = "0.1"
|
129
|
+
|
130
|
+
[dev-dependencies.iai-callgrind]
|
131
|
+
version = "0.16"
|
132
|
+
|
133
|
+
[dev-dependencies.regex]
|
134
|
+
version = "1"
|
135
|
+
|
136
|
+
[target.'cfg(target_arch = "wasm32")'.dependencies.uuid]
|
137
|
+
version = "1"
|
138
|
+
features = ["js"]
|
@@ -0,0 +1,25 @@
|
|
1
|
+
pub(crate) mod pokec;
|
2
|
+
|
3
|
+
pub(crate) fn get_bench_data()
|
4
|
+
{
|
5
|
+
if std::fs::exists("gqlite_bench_data").unwrap()
|
6
|
+
{
|
7
|
+
std::process::Command::new("git")
|
8
|
+
.arg("pull")
|
9
|
+
.spawn()
|
10
|
+
.unwrap()
|
11
|
+
.wait()
|
12
|
+
.unwrap();
|
13
|
+
}
|
14
|
+
else
|
15
|
+
{
|
16
|
+
std::process::Command::new("git")
|
17
|
+
.arg("clone")
|
18
|
+
.arg("https://gitlab.com/auksys/data/gqlite_bench.git")
|
19
|
+
.arg("gqlite_bench_data")
|
20
|
+
.spawn()
|
21
|
+
.unwrap()
|
22
|
+
.wait()
|
23
|
+
.unwrap();
|
24
|
+
}
|
25
|
+
}
|
@@ -0,0 +1,185 @@
|
|
1
|
+
use std::{collections::HashSet, fs};
|
2
|
+
|
3
|
+
use ccutils::temporary::TemporaryFile;
|
4
|
+
use gqlitedb::{map, Connection};
|
5
|
+
use rand::{seq::IndexedRandom, Rng};
|
6
|
+
use regex::Regex;
|
7
|
+
|
8
|
+
pub(crate) struct Pokec
|
9
|
+
{
|
10
|
+
#[allow(dead_code)]
|
11
|
+
temporary_file: TemporaryFile,
|
12
|
+
connection: Connection,
|
13
|
+
ids: Vec<i64>,
|
14
|
+
}
|
15
|
+
|
16
|
+
#[allow(dead_code)]
|
17
|
+
pub(crate) enum PokecSize
|
18
|
+
{
|
19
|
+
Micro,
|
20
|
+
Tiny,
|
21
|
+
}
|
22
|
+
|
23
|
+
impl Pokec
|
24
|
+
{
|
25
|
+
pub(crate) fn load(backend: &str, size: PokecSize) -> Pokec
|
26
|
+
{
|
27
|
+
let temporary_file = TemporaryFile::builder()
|
28
|
+
.should_create_file(false)
|
29
|
+
.label("gqlite_bench")
|
30
|
+
.create();
|
31
|
+
let connection = Connection::open(temporary_file.path(), map!("backend" => backend)).unwrap();
|
32
|
+
|
33
|
+
let filename = match size
|
34
|
+
{
|
35
|
+
PokecSize::Micro => "gqlite_bench_data/pokec_micro_import.cypher",
|
36
|
+
PokecSize::Tiny => "gqlite_bench_data/pokec_tiny_import.cypher",
|
37
|
+
};
|
38
|
+
|
39
|
+
let import_query = fs::read_to_string(filename).unwrap();
|
40
|
+
|
41
|
+
connection
|
42
|
+
.execute_query(import_query, Default::default())
|
43
|
+
.unwrap();
|
44
|
+
Self {
|
45
|
+
temporary_file,
|
46
|
+
connection,
|
47
|
+
ids: Default::default(),
|
48
|
+
}
|
49
|
+
}
|
50
|
+
pub(crate) fn read_ids(mut self) -> Self
|
51
|
+
{
|
52
|
+
let re = Regex::new(r"id:\s*(\d+)").unwrap();
|
53
|
+
let mut ids = HashSet::new();
|
54
|
+
let content = fs::read_to_string("gqlite_bench_data/pokec_tiny_import.cypher")
|
55
|
+
.expect("Failed to read the file");
|
56
|
+
for cap in re.captures_iter(&content)
|
57
|
+
{
|
58
|
+
if let Some(id_match) = cap.get(1)
|
59
|
+
{
|
60
|
+
let id = id_match.as_str().parse::<i64>().unwrap();
|
61
|
+
ids.insert(id);
|
62
|
+
}
|
63
|
+
}
|
64
|
+
self.ids = ids.into_iter().collect();
|
65
|
+
self
|
66
|
+
}
|
67
|
+
pub(crate) fn single_vertex<R>(&self, rng: &mut R)
|
68
|
+
where
|
69
|
+
R: Rng + ?Sized,
|
70
|
+
{
|
71
|
+
let random_id = self.ids.choose(rng).unwrap();
|
72
|
+
self
|
73
|
+
.connection
|
74
|
+
.execute_query(
|
75
|
+
"MATCH (n:User {id: $id}) RETURN n",
|
76
|
+
map!("$id" => *random_id),
|
77
|
+
)
|
78
|
+
.unwrap();
|
79
|
+
}
|
80
|
+
pub(crate) fn single_vertex_where<R>(&self, rng: &mut R)
|
81
|
+
where
|
82
|
+
R: Rng + ?Sized,
|
83
|
+
{
|
84
|
+
let random_id = self.ids.choose(rng).unwrap();
|
85
|
+
self
|
86
|
+
.connection
|
87
|
+
.execute_query(
|
88
|
+
"MATCH (n:User) WHERE n.id = $id RETURN n",
|
89
|
+
map!("$id" => *random_id),
|
90
|
+
)
|
91
|
+
.unwrap();
|
92
|
+
}
|
93
|
+
pub(crate) fn friend_of<R>(&self, rng: &mut R)
|
94
|
+
where
|
95
|
+
R: Rng + ?Sized,
|
96
|
+
{
|
97
|
+
let random_id = self.ids.choose(rng).unwrap();
|
98
|
+
self
|
99
|
+
.connection
|
100
|
+
.execute_query(
|
101
|
+
"MATCH (s:User {id: $id})-->(n:User) RETURN n.id",
|
102
|
+
map!("$id" => *random_id),
|
103
|
+
)
|
104
|
+
.unwrap();
|
105
|
+
}
|
106
|
+
pub(crate) fn friend_of_filter<R>(&self, rng: &mut R)
|
107
|
+
where
|
108
|
+
R: Rng + ?Sized,
|
109
|
+
{
|
110
|
+
let random_id = self.ids.choose(rng).unwrap();
|
111
|
+
self
|
112
|
+
.connection
|
113
|
+
.execute_query(
|
114
|
+
"MATCH (s:User {id: $id})-->(n:User) WHERE n.age >= 18 RETURN n.id",
|
115
|
+
map!("$id" => *random_id),
|
116
|
+
)
|
117
|
+
.unwrap();
|
118
|
+
}
|
119
|
+
pub(crate) fn friend_of_friend_of<R>(&self, rng: &mut R)
|
120
|
+
where
|
121
|
+
R: Rng + ?Sized,
|
122
|
+
{
|
123
|
+
let random_id = self.ids.choose(rng).unwrap();
|
124
|
+
self
|
125
|
+
.connection
|
126
|
+
.execute_query(
|
127
|
+
"MATCH (s:User {id: $id})-->()-->(n:User) RETURN n.id",
|
128
|
+
map!("$id" => *random_id),
|
129
|
+
)
|
130
|
+
.unwrap();
|
131
|
+
}
|
132
|
+
pub(crate) fn friend_of_friend_of_filter<R>(&self, rng: &mut R)
|
133
|
+
where
|
134
|
+
R: Rng + ?Sized,
|
135
|
+
{
|
136
|
+
let random_id = self.ids.choose(rng).unwrap();
|
137
|
+
self
|
138
|
+
.connection
|
139
|
+
.execute_query(
|
140
|
+
"MATCH (s:User {id: $id})-->()-->(n:User) WHERE n.age >= 18 RETURN n.id",
|
141
|
+
map!("$id" => *random_id),
|
142
|
+
)
|
143
|
+
.unwrap();
|
144
|
+
}
|
145
|
+
pub(crate) fn reciprocal_friends<R>(&self, rng: &mut R)
|
146
|
+
where
|
147
|
+
R: Rng + ?Sized,
|
148
|
+
{
|
149
|
+
let random_id = self.ids.choose(rng).unwrap();
|
150
|
+
self
|
151
|
+
.connection
|
152
|
+
.execute_query(
|
153
|
+
"MATCH (n:User {id: $id})-[e1]->(m)-[e2]->(n) RETURN e1, m, e2",
|
154
|
+
map!("$id" => *random_id),
|
155
|
+
)
|
156
|
+
.unwrap();
|
157
|
+
}
|
158
|
+
pub(crate) fn aggregate_count(&self)
|
159
|
+
{
|
160
|
+
self
|
161
|
+
.connection
|
162
|
+
.execute_query("MATCH (n:User) RETURN n.age, count(*)", Default::default())
|
163
|
+
.unwrap();
|
164
|
+
}
|
165
|
+
pub(crate) fn aggregate_count_filter(&self)
|
166
|
+
{
|
167
|
+
self
|
168
|
+
.connection
|
169
|
+
.execute_query(
|
170
|
+
"MATCH (n:User) WHERE n.age >= 18 RETURN n.age, count(*)",
|
171
|
+
Default::default(),
|
172
|
+
)
|
173
|
+
.unwrap();
|
174
|
+
}
|
175
|
+
pub(crate) fn aggregate_min_max_avg(&self)
|
176
|
+
{
|
177
|
+
self
|
178
|
+
.connection
|
179
|
+
.execute_query(
|
180
|
+
"MATCH (n) RETURN min(n.age), max(n.age), avg(n.age)",
|
181
|
+
Default::default(),
|
182
|
+
)
|
183
|
+
.unwrap();
|
184
|
+
}
|
185
|
+
}
|
@@ -0,0 +1,137 @@
|
|
1
|
+
use divan::Bencher;
|
2
|
+
use rand::{rngs::StdRng, SeedableRng};
|
3
|
+
|
4
|
+
mod common;
|
5
|
+
|
6
|
+
use common::pokec::{Pokec, PokecSize};
|
7
|
+
|
8
|
+
const FRIEND_OF_COUNT: u32 = 100;
|
9
|
+
const SINGLE_VERTEX_COUNT: u32 = 100;
|
10
|
+
const IMPORT_COUNT: u32 = 30;
|
11
|
+
|
12
|
+
fn main()
|
13
|
+
{
|
14
|
+
common::get_bench_data();
|
15
|
+
|
16
|
+
// Run registered benchmarks.
|
17
|
+
divan::main();
|
18
|
+
}
|
19
|
+
|
20
|
+
fn load_pokec(backend: &str) -> Pokec
|
21
|
+
{
|
22
|
+
Pokec::load(backend, PokecSize::Tiny)
|
23
|
+
}
|
24
|
+
|
25
|
+
// Import the tiny `pokec` dataset.
|
26
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = IMPORT_COUNT)]
|
27
|
+
fn import_tiny_pokec(backend: &str)
|
28
|
+
{
|
29
|
+
let _ = load_pokec(backend);
|
30
|
+
}
|
31
|
+
|
32
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = SINGLE_VERTEX_COUNT)]
|
33
|
+
fn single_vertex(bencher: Bencher, backend: &str)
|
34
|
+
{
|
35
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
36
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
37
|
+
|
38
|
+
bencher.bench_local(move || {
|
39
|
+
tiny_pokec.single_vertex(&mut rng);
|
40
|
+
});
|
41
|
+
}
|
42
|
+
|
43
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = SINGLE_VERTEX_COUNT)]
|
44
|
+
fn single_vertex_where(bencher: Bencher, backend: &str)
|
45
|
+
{
|
46
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
47
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
48
|
+
|
49
|
+
bencher.bench_local(move || {
|
50
|
+
tiny_pokec.single_vertex_where(&mut rng);
|
51
|
+
});
|
52
|
+
}
|
53
|
+
|
54
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
|
55
|
+
fn friend_of(bencher: Bencher, backend: &str)
|
56
|
+
{
|
57
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
58
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
59
|
+
|
60
|
+
bencher.bench_local(move || {
|
61
|
+
tiny_pokec.friend_of(&mut rng);
|
62
|
+
});
|
63
|
+
}
|
64
|
+
|
65
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
|
66
|
+
fn friend_of_filter(bencher: Bencher, backend: &str)
|
67
|
+
{
|
68
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
69
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
70
|
+
|
71
|
+
bencher.bench_local(move || {
|
72
|
+
tiny_pokec.friend_of_filter(&mut rng);
|
73
|
+
});
|
74
|
+
}
|
75
|
+
|
76
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
|
77
|
+
fn friend_of_friend_of(bencher: Bencher, backend: &str)
|
78
|
+
{
|
79
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
80
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
81
|
+
|
82
|
+
bencher.bench_local(move || {
|
83
|
+
tiny_pokec.friend_of_friend_of(&mut rng);
|
84
|
+
});
|
85
|
+
}
|
86
|
+
|
87
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
|
88
|
+
fn friend_of_friend_of_filter(bencher: Bencher, backend: &str)
|
89
|
+
{
|
90
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
91
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
92
|
+
|
93
|
+
bencher.bench_local(move || {
|
94
|
+
tiny_pokec.friend_of_friend_of_filter(&mut rng);
|
95
|
+
});
|
96
|
+
}
|
97
|
+
|
98
|
+
#[divan::bench(args = ["sqlite", "redb"], sample_count = FRIEND_OF_COUNT)]
|
99
|
+
fn reciprocal_friends(bencher: Bencher, backend: &str)
|
100
|
+
{
|
101
|
+
let tiny_pokec = load_pokec(backend).read_ids();
|
102
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
103
|
+
|
104
|
+
bencher.bench_local(move || {
|
105
|
+
tiny_pokec.reciprocal_friends(&mut rng);
|
106
|
+
});
|
107
|
+
}
|
108
|
+
|
109
|
+
#[divan::bench(args = ["sqlite", "redb"])]
|
110
|
+
fn aggregate_count(bencher: Bencher, backend: &str)
|
111
|
+
{
|
112
|
+
let tiny_pokec = load_pokec(backend);
|
113
|
+
|
114
|
+
bencher.bench_local(move || {
|
115
|
+
tiny_pokec.aggregate_count();
|
116
|
+
});
|
117
|
+
}
|
118
|
+
|
119
|
+
#[divan::bench(args = ["sqlite", "redb"])]
|
120
|
+
fn aggregate_count_filter(bencher: Bencher, backend: &str)
|
121
|
+
{
|
122
|
+
let tiny_pokec = load_pokec(backend);
|
123
|
+
|
124
|
+
bencher.bench_local(move || {
|
125
|
+
tiny_pokec.aggregate_count_filter();
|
126
|
+
});
|
127
|
+
}
|
128
|
+
|
129
|
+
#[divan::bench(args = ["sqlite", "redb"])]
|
130
|
+
fn aggregate_min_max_avg(bencher: Bencher, backend: &str)
|
131
|
+
{
|
132
|
+
let tiny_pokec = load_pokec(backend);
|
133
|
+
|
134
|
+
bencher.bench_local(move || {
|
135
|
+
tiny_pokec.aggregate_min_max_avg();
|
136
|
+
});
|
137
|
+
}
|
@@ -0,0 +1,122 @@
|
|
1
|
+
use std::hint::black_box;
|
2
|
+
|
3
|
+
use iai_callgrind::{library_benchmark, library_benchmark_group, main};
|
4
|
+
use rand::{rngs::StdRng, SeedableRng};
|
5
|
+
|
6
|
+
mod common;
|
7
|
+
|
8
|
+
use common::pokec::{Pokec, PokecSize};
|
9
|
+
|
10
|
+
fn load_pokec(backend: &str) -> Pokec
|
11
|
+
{
|
12
|
+
Pokec::load(backend, PokecSize::Micro)
|
13
|
+
}
|
14
|
+
|
15
|
+
fn load_with_ids(backend: &str) -> Pokec
|
16
|
+
{
|
17
|
+
load_pokec(backend).read_ids()
|
18
|
+
}
|
19
|
+
|
20
|
+
#[library_benchmark]
|
21
|
+
#[bench::redb("redb")]
|
22
|
+
#[bench::sqlite("sqlite")]
|
23
|
+
fn import_micro_pokec(backend: &str)
|
24
|
+
{
|
25
|
+
black_box(load_pokec(backend));
|
26
|
+
}
|
27
|
+
|
28
|
+
#[library_benchmark(setup = load_with_ids)]
|
29
|
+
#[bench::redb("redb")]
|
30
|
+
#[bench::sqlite("sqlite")]
|
31
|
+
fn single_vertex(micro_pokec: Pokec)
|
32
|
+
{
|
33
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
34
|
+
micro_pokec.single_vertex(&mut rng);
|
35
|
+
}
|
36
|
+
|
37
|
+
#[library_benchmark(setup = load_with_ids)]
|
38
|
+
#[bench::redb("redb")]
|
39
|
+
#[bench::sqlite("sqlite")]
|
40
|
+
fn single_vertex_where(micro_pokec: Pokec)
|
41
|
+
{
|
42
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
43
|
+
micro_pokec.single_vertex_where(&mut rng);
|
44
|
+
}
|
45
|
+
|
46
|
+
#[library_benchmark(setup = load_with_ids)]
|
47
|
+
#[bench::redb("redb")]
|
48
|
+
#[bench::sqlite("sqlite")]
|
49
|
+
fn friend_of(micro_pokec: Pokec)
|
50
|
+
{
|
51
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
52
|
+
micro_pokec.friend_of(&mut rng);
|
53
|
+
}
|
54
|
+
|
55
|
+
#[library_benchmark(setup = load_with_ids)]
|
56
|
+
#[bench::redb("redb")]
|
57
|
+
#[bench::sqlite("sqlite")]
|
58
|
+
fn friend_of_filter(micro_pokec: Pokec)
|
59
|
+
{
|
60
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
61
|
+
micro_pokec.friend_of_filter(&mut rng);
|
62
|
+
}
|
63
|
+
|
64
|
+
#[library_benchmark(setup = load_with_ids)]
|
65
|
+
#[bench::redb("redb")]
|
66
|
+
#[bench::sqlite("sqlite")]
|
67
|
+
fn friend_of_friend_of(micro_pokec: Pokec)
|
68
|
+
{
|
69
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
70
|
+
micro_pokec.friend_of_friend_of(&mut rng);
|
71
|
+
}
|
72
|
+
|
73
|
+
#[library_benchmark(setup = load_with_ids)]
|
74
|
+
#[bench::redb("redb")]
|
75
|
+
#[bench::sqlite("sqlite")]
|
76
|
+
fn friend_of_friend_of_filter(micro_pokec: Pokec)
|
77
|
+
{
|
78
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
79
|
+
micro_pokec.friend_of_friend_of_filter(&mut rng);
|
80
|
+
}
|
81
|
+
|
82
|
+
#[library_benchmark(setup = load_with_ids)]
|
83
|
+
#[bench::redb("redb")]
|
84
|
+
#[bench::sqlite("sqlite")]
|
85
|
+
fn reciprocal_friends(micro_pokec: Pokec)
|
86
|
+
{
|
87
|
+
let mut rng = StdRng::seed_from_u64(991173);
|
88
|
+
micro_pokec.reciprocal_friends(&mut rng);
|
89
|
+
}
|
90
|
+
|
91
|
+
#[library_benchmark(setup = load_pokec)]
|
92
|
+
#[bench::redb("redb")]
|
93
|
+
#[bench::sqlite("sqlite")]
|
94
|
+
fn aggregate_count(micro_pokec: Pokec)
|
95
|
+
{
|
96
|
+
micro_pokec.aggregate_count();
|
97
|
+
}
|
98
|
+
|
99
|
+
#[library_benchmark(setup = load_pokec)]
|
100
|
+
#[bench::redb("redb")]
|
101
|
+
#[bench::sqlite("sqlite")]
|
102
|
+
fn aggregate_count_filter(micro_pokec: Pokec)
|
103
|
+
{
|
104
|
+
micro_pokec.aggregate_count_filter();
|
105
|
+
}
|
106
|
+
|
107
|
+
#[library_benchmark(setup = load_pokec)]
|
108
|
+
#[bench::redb("redb")]
|
109
|
+
#[bench::sqlite("sqlite")]
|
110
|
+
fn aggregate_min_max_avg(micro_pokec: Pokec)
|
111
|
+
{
|
112
|
+
micro_pokec.aggregate_min_max_avg();
|
113
|
+
}
|
114
|
+
|
115
|
+
library_benchmark_group!(
|
116
|
+
name = bench_micro_pokec_group;
|
117
|
+
benchmarks = import_micro_pokec, single_vertex, single_vertex_where, friend_of, friend_of_filter, friend_of_friend_of, friend_of_friend_of_filter, reciprocal_friends, aggregate_count, aggregate_count_filter, aggregate_min_max_avg
|
118
|
+
);
|
119
|
+
|
120
|
+
main!(
|
121
|
+
setup = common::get_bench_data();
|
122
|
+
library_benchmark_groups = bench_micro_pokec_group);
|
@@ -0,0 +1,7 @@
|
|
1
|
+
pre-release-replacements = [
|
2
|
+
{ file = "../../CHANGELOG.md", search = "Unreleased", replace = "{{version}}" },
|
3
|
+
{ file = "../../CHANGELOG.md", search = "\\.\\.\\.dev/1", replace = "...{{tag_name}}", exactly = 1 },
|
4
|
+
{ file = "../../CHANGELOG.md", search = "ReleaseDate", replace = "{{date}}" },
|
5
|
+
{ file = "../../CHANGELOG.md", search = "<!-- next-header -->", replace = "<!-- next-header -->\n\n## [Unreleased] - ReleaseDate", exactly = 1 },
|
6
|
+
{ file = "../../CHANGELOG.md", search = "<!-- next-url -->", replace = "<!-- next-url -->\n[Unreleased]: https://gitlab.com/gqlite/gqlite/compare/{{tag_name}}...dev/1", exactly = 1 },
|
7
|
+
]
|
@@ -0,0 +1,96 @@
|
|
1
|
+
use std::fmt::Debug;
|
2
|
+
|
3
|
+
use super::AggregatorState;
|
4
|
+
|
5
|
+
use crate::{error::RunTimeError, value::Value, Result};
|
6
|
+
|
7
|
+
trait Op
|
8
|
+
{
|
9
|
+
fn op_i64(a: i64, b: i64) -> i64;
|
10
|
+
fn op_f64(a: f64, b: f64) -> f64;
|
11
|
+
}
|
12
|
+
|
13
|
+
#[derive(Debug)]
|
14
|
+
struct OpState<T>
|
15
|
+
where
|
16
|
+
T: Op + Debug,
|
17
|
+
{
|
18
|
+
value: Value,
|
19
|
+
_marker: std::marker::PhantomData<T>,
|
20
|
+
}
|
21
|
+
|
22
|
+
impl<T> OpState<T>
|
23
|
+
where
|
24
|
+
T: Op + Debug,
|
25
|
+
{
|
26
|
+
fn new() -> Result<Self>
|
27
|
+
{
|
28
|
+
Ok(Self {
|
29
|
+
value: Value::Null,
|
30
|
+
_marker: Default::default(),
|
31
|
+
})
|
32
|
+
}
|
33
|
+
}
|
34
|
+
|
35
|
+
impl<T> AggregatorState for OpState<T>
|
36
|
+
where
|
37
|
+
T: Op + Debug,
|
38
|
+
{
|
39
|
+
fn next(&mut self, value: Value) -> crate::Result<()>
|
40
|
+
{
|
41
|
+
match self.value
|
42
|
+
{
|
43
|
+
Value::Boolean(..)
|
44
|
+
| Value::Node(..)
|
45
|
+
| Value::Edge(..)
|
46
|
+
| Value::Array(..)
|
47
|
+
| Value::String(..)
|
48
|
+
| Value::Map(..)
|
49
|
+
| Value::Path(..) => Err(RunTimeError::InvalidBinaryOperands)?,
|
50
|
+
Value::Null =>
|
51
|
+
{
|
52
|
+
self.value = value;
|
53
|
+
}
|
54
|
+
Value::Float(state) => match value
|
55
|
+
{
|
56
|
+
Value::Null =>
|
57
|
+
{}
|
58
|
+
Value::Float(new_value) => self.value = T::op_f64(state, new_value).into(),
|
59
|
+
Value::Integer(new_value) => self.value = T::op_f64(state, new_value as f64).into(),
|
60
|
+
_ => Err(RunTimeError::InvalidBinaryOperands)?,
|
61
|
+
},
|
62
|
+
Value::Integer(state) => match value
|
63
|
+
{
|
64
|
+
Value::Null =>
|
65
|
+
{}
|
66
|
+
Value::Float(new_value) => self.value = T::op_f64(state as f64, new_value).into(),
|
67
|
+
Value::Integer(new_value) => self.value = T::op_i64(state, new_value).into(),
|
68
|
+
_ => Err(RunTimeError::InvalidBinaryOperands)?,
|
69
|
+
},
|
70
|
+
}
|
71
|
+
Ok(())
|
72
|
+
}
|
73
|
+
fn finalise(self: Box<Self>) -> crate::Result<crate::value::Value>
|
74
|
+
{
|
75
|
+
Ok(self.value)
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
#[derive(Debug)]
|
80
|
+
struct SumOp;
|
81
|
+
|
82
|
+
impl Op for SumOp
|
83
|
+
{
|
84
|
+
fn op_f64(a: f64, b: f64) -> f64
|
85
|
+
{
|
86
|
+
a + b
|
87
|
+
}
|
88
|
+
fn op_i64(a: i64, b: i64) -> i64
|
89
|
+
{
|
90
|
+
a + b
|
91
|
+
}
|
92
|
+
}
|
93
|
+
|
94
|
+
type SumState = OpState<SumOp>;
|
95
|
+
|
96
|
+
super::declare_aggregator!(sum, Sum, SumState, () -> i64);
|