1 | #include "benchmark_runner.hpp" |
2 | #include "duckdb_benchmark_macro.hpp" |
3 | #include "duckdb/main/appender.hpp" |
4 | |
5 | using namespace duckdb; |
6 | using namespace std; |
7 | |
8 | ////////////// |
9 | // INSERT // |
10 | ////////////// |
11 | #define APPEND_BENCHMARK_INSERT(CREATE_STATEMENT, AUTO_COMMIT) \ |
12 | void Load(DuckDBBenchmarkState *state) override { \ |
13 | state->conn.Query(CREATE_STATEMENT); \ |
14 | } \ |
15 | void RunBenchmark(DuckDBBenchmarkState *state) override { \ |
16 | if (!AUTO_COMMIT) \ |
17 | state->conn.Query("BEGIN TRANSACTION"); \ |
18 | for (int32_t i = 0; i < 100000; i++) { \ |
19 | state->conn.Query("INSERT INTO integers VALUES (" + to_string(i) + ")"); \ |
20 | } \ |
21 | if (!AUTO_COMMIT) \ |
22 | state->conn.Query("COMMIT"); \ |
23 | } \ |
24 | void Cleanup(DuckDBBenchmarkState *state) override { \ |
25 | state->conn.Query("DROP TABLE integers"); \ |
26 | Load(state); \ |
27 | } \ |
28 | string VerifyResult(QueryResult *result) override { \ |
29 | return string(); \ |
30 | } \ |
31 | string BenchmarkInfo() override { \ |
32 | return "Append 100K 4-byte integers to a table using a series of INSERT INTO statements"; \ |
33 | } |
34 | |
35 | DUCKDB_BENCHMARK(Append100KIntegersINSERT, "[append]" ) |
36 | APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)" , false) |
37 | FINISH_BENCHMARK(Append100KIntegersINSERT) |
38 | |
39 | DUCKDB_BENCHMARK(Append100KIntegersINSERTDisk, "[append]" ) |
40 | APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)" , false) |
41 | bool InMemory() override { |
42 | return false; |
43 | } |
44 | FINISH_BENCHMARK(Append100KIntegersINSERTDisk) |
45 | |
46 | DUCKDB_BENCHMARK(Append100KIntegersINSERTPrimary, "[append]" ) |
47 | APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER PRIMARY KEY)" , false) |
48 | FINISH_BENCHMARK(Append100KIntegersINSERTPrimary) |
49 | |
50 | DUCKDB_BENCHMARK(Append100KIntegersINSERTAutoCommit, "[append]" ) |
51 | APPEND_BENCHMARK_INSERT("CREATE TABLE integers(i INTEGER)" , true) |
52 | FINISH_BENCHMARK(Append100KIntegersINSERTAutoCommit) |
53 | |
54 | ////////////// |
55 | // PREPARED // |
56 | ////////////// |
57 | struct DuckDBPreparedState : public DuckDBBenchmarkState { |
58 | unique_ptr<PreparedStatement> prepared; |
59 | |
60 | DuckDBPreparedState(string path) : DuckDBBenchmarkState(path) { |
61 | } |
62 | virtual ~DuckDBPreparedState() { |
63 | } |
64 | }; |
65 | |
66 | #define APPEND_BENCHMARK_PREPARED(CREATE_STATEMENT) \ |
67 | unique_ptr<DuckDBBenchmarkState> CreateBenchmarkState() override { \ |
68 | auto result = make_unique<DuckDBPreparedState>(GetDatabasePath()); \ |
69 | return move(result); \ |
70 | } \ |
71 | void Load(DuckDBBenchmarkState *state_) override { \ |
72 | auto state = (DuckDBPreparedState *)state_; \ |
73 | state->conn.Query(CREATE_STATEMENT); \ |
74 | state->prepared = state->conn.Prepare("INSERT INTO integers VALUES ($1)"); \ |
75 | } \ |
76 | void RunBenchmark(DuckDBBenchmarkState *state_) override { \ |
77 | auto state = (DuckDBPreparedState *)state_; \ |
78 | state->conn.Query("BEGIN TRANSACTION"); \ |
79 | for (int32_t i = 0; i < 100000; i++) { \ |
80 | state->prepared->Execute(i); \ |
81 | } \ |
82 | state->conn.Query("COMMIT"); \ |
83 | } \ |
84 | void Cleanup(DuckDBBenchmarkState *state) override { \ |
85 | state->conn.Query("DROP TABLE integers"); \ |
86 | Load(state); \ |
87 | } \ |
88 | string VerifyResult(QueryResult *result) override { \ |
89 | return string(); \ |
90 | } \ |
91 | string BenchmarkInfo() override { \ |
92 | return "Append 100K 4-byte integers to a table using a series of prepared INSERT INTO statements"; \ |
93 | } |
94 | |
95 | DUCKDB_BENCHMARK(Append100KIntegersPREPARED, "[append]" ) |
96 | APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER)" ) |
97 | FINISH_BENCHMARK(Append100KIntegersPREPARED) |
98 | |
99 | DUCKDB_BENCHMARK(Append100KIntegersPREPAREDDisk, "[append]" ) |
100 | APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER)" ) |
101 | bool InMemory() override { |
102 | return false; |
103 | } |
104 | FINISH_BENCHMARK(Append100KIntegersPREPAREDDisk) |
105 | |
106 | DUCKDB_BENCHMARK(Append100KIntegersPREPAREDPrimary, "[append]" ) |
107 | APPEND_BENCHMARK_PREPARED("CREATE TABLE integers(i INTEGER PRIMARY KEY)" ) |
108 | FINISH_BENCHMARK(Append100KIntegersPREPAREDPrimary) |
109 | |
110 | ////////////// |
111 | // APPENDER // |
112 | ////////////// |
113 | #define APPEND_BENCHMARK_APPENDER(CREATE_STATEMENT) \ |
114 | void Load(DuckDBBenchmarkState *state) override { \ |
115 | state->conn.Query(CREATE_STATEMENT); \ |
116 | } \ |
117 | void RunBenchmark(DuckDBBenchmarkState *state) override { \ |
118 | state->conn.Query("BEGIN QUERY"); \ |
119 | Appender appender(state->conn, "integers"); \ |
120 | for (int32_t i = 0; i < 100000; i++) { \ |
121 | appender.BeginRow(); \ |
122 | appender.Append<int32_t>(i); \ |
123 | appender.EndRow(); \ |
124 | } \ |
125 | appender.Close(); \ |
126 | state->conn.Query("COMMIT"); \ |
127 | } \ |
128 | void Cleanup(DuckDBBenchmarkState *state) override { \ |
129 | state->conn.Query("DROP TABLE integers"); \ |
130 | Load(state); \ |
131 | } \ |
132 | string VerifyResult(QueryResult *result) override { \ |
133 | return string(); \ |
134 | } \ |
135 | string BenchmarkInfo() override { \ |
136 | return "Append 100K 4-byte integers to a table using an Appender"; \ |
137 | } |
138 | |
139 | DUCKDB_BENCHMARK(Append100KIntegersAPPENDER, "[append]" ) |
140 | APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER)" ) |
141 | FINISH_BENCHMARK(Append100KIntegersAPPENDER) |
142 | |
143 | DUCKDB_BENCHMARK(Append100KIntegersAPPENDERDisk, "[append]" ) |
144 | APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER)" ) |
145 | bool InMemory() override { |
146 | return false; |
147 | } |
148 | FINISH_BENCHMARK(Append100KIntegersAPPENDERDisk) |
149 | |
150 | DUCKDB_BENCHMARK(Append100KIntegersAPPENDERPrimary, "[append]" ) |
151 | APPEND_BENCHMARK_APPENDER("CREATE TABLE integers(i INTEGER PRIMARY KEY)" ) |
152 | FINISH_BENCHMARK(Append100KIntegersAPPENDERPrimary) |
153 | |
154 | /////////////// |
155 | // COPY INTO // |
156 | /////////////// |
157 | #define APPEND_BENCHMARK_COPY(CREATE_STATEMENT) \ |
158 | void Load(DuckDBBenchmarkState *state) override { \ |
159 | state->conn.Query("CREATE TABLE integers(i INTEGER)"); \ |
160 | Appender appender(state->conn, "integers"); \ |
161 | for (int32_t i = 0; i < 100000; i++) { \ |
162 | appender.BeginRow(); \ |
163 | appender.Append<int32_t>(i); \ |
164 | appender.EndRow(); \ |
165 | } \ |
166 | appender.Close(); \ |
167 | state->conn.Query("COPY integers TO 'integers.csv' DELIMITER '|'"); \ |
168 | state->conn.Query("DROP TABLE integers"); \ |
169 | state->conn.Query(CREATE_STATEMENT); \ |
170 | } \ |
171 | string GetQuery() override { \ |
172 | return "COPY integers FROM 'integers.csv' DELIMITER '|'"; \ |
173 | } \ |
174 | void Cleanup(DuckDBBenchmarkState *state) override { \ |
175 | state->conn.Query("DROP TABLE integers"); \ |
176 | state->conn.Query(CREATE_STATEMENT); \ |
177 | } \ |
178 | string VerifyResult(QueryResult *result) override { \ |
179 | return string(); \ |
180 | } \ |
181 | string BenchmarkInfo() override { \ |
182 | return "Append 100K 4-byte integers to a table using the COPY INTO statement"; \ |
183 | } |
184 | |
185 | DUCKDB_BENCHMARK(Append100KIntegersCOPY, "[append]" ) |
186 | APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER)" ) |
187 | FINISH_BENCHMARK(Append100KIntegersCOPY) |
188 | |
189 | DUCKDB_BENCHMARK(Append100KIntegersCOPYDisk, "[append]" ) |
190 | APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER)" ) |
191 | bool InMemory() override { |
192 | return false; |
193 | } |
194 | FINISH_BENCHMARK(Append100KIntegersCOPYDisk) |
195 | |
196 | DUCKDB_BENCHMARK(Append100KIntegersCOPYPrimary, "[append]" ) |
197 | APPEND_BENCHMARK_COPY("CREATE TABLE integers(i INTEGER PRIMARY KEY)" ) |
198 | FINISH_BENCHMARK(Append100KIntegersCOPYPrimary) |
199 | |
200 | DUCKDB_BENCHMARK(Write100KIntegers, "[append]" ) |
201 | void Load(DuckDBBenchmarkState *state) override { |
202 | state->conn.Query("CREATE TABLE integers(i INTEGER)" ); |
203 | Appender appender(state->conn, "integers" ); |
204 | for (int32_t i = 0; i < 100000; i++) { |
205 | appender.BeginRow(); |
206 | appender.Append<int32_t>(i); |
207 | appender.EndRow(); |
208 | } |
209 | } |
210 | string GetQuery() override { |
211 | return "COPY integers TO 'integers.csv' DELIMITER '|' HEADER" ; |
212 | } |
213 | string VerifyResult(QueryResult *result) override { |
214 | if (!result->success) { |
215 | return result->error; |
216 | } |
217 | return string(); |
218 | } |
219 | string BenchmarkInfo() override { |
220 | return "Write 100K 4-byte integers to CSV" ; |
221 | } |
222 | FINISH_BENCHMARK(Write100KIntegers) |
223 | |