Skip to content

Commit 0171241

Browse files
authored
Merge pull request #6 from duckdb/jray/api-benchmarks
api benchmarks
2 parents c249cca + 805f5d1 commit 0171241

12 files changed

+178
-1
lines changed

api/package.json

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@
66
"build:test": "tsc -b test",
77
"clean": "rimraf pkgs/@duckdb/node-api/lib",
88
"test": "vitest run",
9-
"test:watch": "vitest"
9+
"test:watch": "vitest",
10+
"bench": "vitest bench --run",
11+
"bench:watch": "vitest bench"
1012
},
1113
"dependencies": {
1214
"@duckdb/node-bindings": "workspace:*"

api/test/bench/types_bit.bench.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (bit)', () => {
5+
bench('bit (small)', benchFn(`select '101010'::bit from range(1000000)`), benchOpts());
6+
bench('bit (short)', benchFn(`select bitstring('0101011', 11 * 8) from range(1000000)`), benchOpts());
7+
bench('bit (short + 1 = smallest long)', benchFn(`select bitstring('0101011', 11 * 8 + 1) from range(1000000)`), benchOpts());
8+
bench('bit (long)', benchFn(`select bitstring('0101011', 11 * 8 + 12 * 8) from range(1000000)`), benchOpts());
9+
});
+23
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (date)', () => {
5+
bench('date', benchFn(`select '2123-12-31'::date from range(1000000)`), benchOpts());
6+
});
7+
8+
describe('types (time)', () => {
9+
bench('time', benchFn(`select '12:34:56.789123'::time from range(1000000)`), benchOpts());
10+
bench('timetz', benchFn(`select '12:34:56-15:59:59'::timetz from range(1000000)`), benchOpts());
11+
});
12+
13+
describe('types (timestamp)', () => {
14+
bench('timestamp', benchFn(`select '2123-12-31 12:34:56.789123'::timestamp from range(1000000)`), benchOpts());
15+
bench('timestamp_s', benchFn(`select '2123-12-31 12:34:56'::timestamp_s from range(1000000)`), benchOpts());
16+
bench('timestamp_ms', benchFn(`select '2123-12-31 12:34:56.789'::timestamp_ms from range(1000000)`), benchOpts());
17+
bench('timestamp_ns', benchFn(`select '2123-12-31 12:34:56.789123'::timestamp_ns from range(1000000)`), benchOpts());
18+
bench('timestamptz', benchFn(`select '2123-12-31 12:34:56.789123'::timestamptz from range(1000000)`), benchOpts());
19+
});
20+
21+
describe('types (interval)', () => {
22+
bench('interval', benchFn('select interval 1 minute from range(1000000)'), benchOpts());
23+
});

api/test/bench/types_enum.bench.ts

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (enum)', () => {
5+
bench('enum (small)', benchFn(`select 'a'::small_enum from range(1000000)`), benchOpts({
6+
additionalSetup: async (connection) => {
7+
await connection.run(`create type small_enum as enum ('a', 'b')`);
8+
},
9+
}));
10+
bench('enum (medium)', benchFn(`select 'enum_0'::medium_enum from range(1000000)`), benchOpts({
11+
additionalSetup: async (connection) => {
12+
await connection.run(`create type medium_enum as enum (select 'enum_' || i from range(300) t(i))`);
13+
}
14+
}));
15+
bench.skip('enum (large)', benchFn(`select 'enum_0'::large_enum from range(1000000)`), benchOpts({
16+
additionalSetup: async (connection) => {
17+
await connection.run(`create type large_enum as enum (select 'enum_' || i from range(70000) t(i))`);
18+
}
19+
}));
20+
});

api/test/bench/types_list.bench.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (list & array)', () => {
5+
bench('list[int]', benchFn('select [1] from range(1000000)'), benchOpts());
6+
bench('list[varchar]', benchFn(`select ['a'] from range(1000000)`), benchOpts());
7+
bench('array[int]', benchFn('select array_value(1) from range(1000000)'), benchOpts());
8+
bench('array[varchar]', benchFn(`select array_value('a') from range(1000000)`), benchOpts());
9+
});

api/test/bench/types_misc.bench.ts

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (bool)', () => {
5+
bench('bool', benchFn('select true from range(1000000)'), benchOpts());
6+
});
7+
8+
describe('types (uuid)', () => {
9+
bench('uuid', benchFn('select uuid() from range(1000000)'), benchOpts());
10+
});
11+
12+
describe('types (union)', () => {
13+
bench('union', benchFn(`select union_value(t := 'a') from range(1000000)`), benchOpts());
14+
});

api/test/bench/types_numeric.bench.ts

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (numeric)', () => {
5+
bench('tinyint', benchFn('select 1::tinyint from range(1000000)'), benchOpts());
6+
bench('smallint', benchFn('select 1::smallint from range(1000000)'), benchOpts());
7+
bench('integer', benchFn('select 1::integer from range(1000000)'), benchOpts());
8+
bench('bigint', benchFn('select 1::bigint from range(1000000)'), benchOpts());
9+
bench('hugeint', benchFn('select 1::hugeint from range(1000000)'), benchOpts());
10+
11+
bench('utinyint', benchFn('select 1::utinyint from range(1000000)'), benchOpts());
12+
bench('usmallint', benchFn('select 1::usmallint from range(1000000)'), benchOpts());
13+
bench('uinteger', benchFn('select 1::uinteger from range(1000000)'), benchOpts());
14+
bench('ubigint', benchFn('select 1::ubigint from range(1000000)'), benchOpts());
15+
bench('uhugeint', benchFn('select 1::uhugeint from range(1000000)'), benchOpts());
16+
17+
bench('float', benchFn('select 1::float from range(1000000)'), benchOpts());
18+
bench('double', benchFn('select 1::double from range(1000000)'), benchOpts());
19+
20+
bench('decimal (2 bytes)', benchFn('select 999.9::decimal(4,1) from range(1000000)'), benchOpts());
21+
bench('decimal (4 bytes)', benchFn('select 99999.9999::decimal(9,4) from range(1000000)'), benchOpts());
22+
bench('decimal (8 bytes)', benchFn('select 999999999999.999999::decimal(18,6) from range(1000000)'), benchOpts());
23+
bench('decimal (16 bytes)', benchFn('select 9999999999999999999999999999.9999999999::decimal(38,10) from range(1000000)'), benchOpts());
24+
});

api/test/bench/types_struct.bench.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (struct & map)', () => {
5+
bench('struct[int]', benchFn('select {a:1} from range(1000000)'), benchOpts());
6+
bench('struct[varchar]', benchFn(`select {a:'a'} from range(1000000)`), benchOpts());
7+
bench('map[int,int]', benchFn('select map {1:1} from range(1000000)'), benchOpts());
8+
bench('map[varchar,varchar]', benchFn(`select map {'a':'a'} from range(1000000)`), benchOpts());
9+
});

api/test/bench/types_varchar.bench.ts

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('types (varchar & blob)', () => {
5+
bench('varchar (short)', benchFn(`select 'abcdefghijkl' from range(1000000)`), benchOpts());
6+
bench('varchar (long)', benchFn(`select 'abcdefghijklmnopqrstuvwx' from range(1000000)`), benchOpts());
7+
bench('blob (short)', benchFn(`select 'abcdefghijkl'::blob from range(1000000)`), benchOpts());
8+
bench('blob (long)', benchFn(`select 'abcdefghijklmnopqrstuvwx'::blob from range(1000000)`), benchOpts());
9+
});

api/test/bench/util/benchUtils.ts

+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import { DuckDBConnection, DuckDBInstance } from '../../../src';
2+
import { runSql } from './runSql';
3+
4+
let instance: DuckDBInstance;
5+
let connection: DuckDBConnection;
6+
7+
async function setupConnection() {
8+
instance = await DuckDBInstance.create();
9+
connection = await instance.connect();
10+
}
11+
12+
async function teardownConnection() {
13+
await connection.dispose();
14+
await instance.dispose();
15+
}
16+
17+
export function benchFn(sql: string) {
18+
return () => runSql(connection, sql);
19+
}
20+
21+
export function benchOpts(options?: { additionalSetup?: (connection: DuckDBConnection) => Promise<void> }) {
22+
const additionalSetup = options?.additionalSetup;
23+
const setup = additionalSetup ? (
24+
async () => {
25+
await setupConnection();
26+
await additionalSetup(connection);
27+
}
28+
) : setupConnection;
29+
const teardown = teardownConnection;
30+
return { setup, teardown };
31+
}

api/test/bench/util/runSql.ts

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { DuckDBConnection } from '../../../src';
2+
3+
export async function runSql(connection: DuckDBConnection, sql: string): Promise<void> {
4+
const result = await connection.run(sql);
5+
let valueCount = 0;
6+
let nullCount = 0;
7+
let chunk = await result.fetchChunk();
8+
while (chunk.rowCount > 0) {
9+
const col0 = chunk.getColumn(0);
10+
for (let i = 0; i < col0.itemCount; i++) {
11+
if (col0.getItem(i) === null) {
12+
nullCount++;
13+
} else {
14+
valueCount++;
15+
}
16+
}
17+
chunk.dispose();
18+
chunk = await result.fetchChunk();
19+
}
20+
chunk.dispose();
21+
}

api/test/bench/validity.bench.ts

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
import { bench, describe } from 'vitest';
2+
import { benchFn, benchOpts } from './util/benchUtils';
3+
4+
describe('validity', () => {
5+
bench('odds null', benchFn('SELECT CASE WHEN range % 2 = 0 THEN range ELSE NULL END asdf FROM range(1000000)'), benchOpts());
6+
});

0 commit comments

Comments
 (0)