Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto run benchmarks #160

Open
wants to merge 35 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
7134584
proof of concept for using http2 instead of axios
vkarpov15 Nov 21, 2023
f59b1c2
fix TS build issues
vkarpov15 Nov 21, 2023
e30f026
error handling improvements
vkarpov15 Nov 25, 2023
211060f
clean up a bunch of dangling references
vkarpov15 Nov 25, 2023
a9d58f8
clean up all dangling http2 sessions in tests so test process exits a…
vkarpov15 Nov 26, 2023
edb27ff
make collections reuse provided http client
vkarpov15 Dec 1, 2023
df4ae56
reuse same HTTP client for all databases as well as collections
vkarpov15 Dec 1, 2023
0999889
refactor out HTTP2 request logic into a separate function
vkarpov15 Dec 2, 2023
1fefe9c
confirm that Mongoose close() and disconnect() correctly disconnect h…
vkarpov15 Dec 3, 2023
e263737
better typings for http2 internals
vkarpov15 Dec 3, 2023
17a66a8
test double closing httpClient
vkarpov15 Dec 3, 2023
6d31cac
first benchmark
vkarpov15 Dec 23, 2023
c2ba992
add 2nd benchmark script
vkarpov15 Dec 23, 2023
2ab00cc
add 2 more benchmarks, run all benchmarks with npm run benchmark
vkarpov15 Dec 24, 2023
bdc2726
add vector benchmarks
vkarpov15 Dec 25, 2023
8b3e87d
quick fix to make benchmark script run
vkarpov15 Dec 25, 2023
1a001a0
add benchmarks that run against astra
vkarpov15 Dec 26, 2023
f6c78e3
add benchmarks workflow
vkarpov15 Dec 26, 2023
5959071
fix workflows config
vkarpov15 Dec 26, 2023
490b7b2
fix workflow name
vkarpov15 Dec 26, 2023
483d1c6
rename benchmark script, print file output instead of uploading artif…
vkarpov15 Dec 26, 2023
bc210ce
add script to upload benchmark results
vkarpov15 Dec 26, 2023
c126903
add switch to enable/disable http2
vkarpov15 Dec 28, 2023
205e30f
Merge branch 'vkarpov15/http2' into vkarpov15/benchmarks
vkarpov15 Dec 28, 2023
ae82eb1
a couple of quick benchmark fixes
vkarpov15 Dec 28, 2023
e1b7adc
properly pass useHTTP2 down to httpClient
vkarpov15 Dec 28, 2023
2513784
Merge branch 'vkarpov15/http2' into vkarpov15/benchmarks
vkarpov15 Dec 28, 2023
878ae37
add working http2 benchmark that shows http2 is 3x faster than http1
vkarpov15 Dec 28, 2023
4df1941
add basic README for benchmarks
vkarpov15 Dec 28, 2023
14c6535
Merge branch 'main' into vkarpov15/benchmarks
vkarpov15 Jan 7, 2024
15e5c03
add script to setup benchmark data for comparing http1 vs http2
vkarpov15 Jan 7, 2024
6a4b19e
Merge branch 'main' into vkarpov15/benchmarks
vkarpov15 Feb 20, 2024
b8ac5ab
create collection if not found for astra vector benchmark
vkarpov15 Feb 20, 2024
13588e1
use correct script for astra vector setup
vkarpov15 Feb 20, 2024
5ea1ce6
add pinecone benchmarks and quick fixes for Astra benchmarks
vkarpov15 Feb 20, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/benchmarks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
name: Benchmarks - stargate-mongoose
on:
pull_request:
push:
jobs:
benchmarks:
runs-on: ubuntu-latest
steps:
- name: disable and stop mono-xsp4.service
run: |
sudo kill -9 $(sudo lsof -t -i:8084)
- uses: actions/checkout@v3
- name: Set up JSON API
run: |
chmod +x bin/start_json_api.sh
bin/start_json_api.sh
- name: Wait for services
run: |
while ! nc -z localhost 8181; do sleep 1; done
while ! nc -z localhost 8081; do sleep 1; done
- name: Setting up the node version
uses: actions/setup-node@v3
with:
node-version: 16.15.0
- name: setup project
run: npm i
- name: benchmarks
run: npm run benchmarks
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ node_modules
.vscode
dist
package-lock.json
.idea
.idea
*.out
*.tgz
4 changes: 3 additions & 1 deletion .npmignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,6 @@ tests
.env.example
.github

*.tgz
*.tgz

benchmarks
4 changes: 4 additions & 0 deletions benchmarks/.env.benchmark
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
JSON_API_URI=http://127.0.0.1:8181/v1/benchmark
JSON_API_USERNAME=cassandra
JSON_API_PASSWORD=cassandra
JSON_API_AUTH_URL=http://127.0.0.1:8081/v1/auth
95 changes: 95 additions & 0 deletions benchmarks/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
# Benchmarks

Each `benchmark-*.ts` file is a separate benchmark that tests different functionality.
Benchmarks use either stargate-mongoose or the Axios HTTP client directly; this is to check whether stargate-mongoose is adding significant overhead or not.

## Running Benchmarks

The easiest way to run all benchmarks is using the following npm command:

```
npm run benchmarks
```

This will run all benchmarks, and output results to both stdout and `.out` files in the `benchmarks` directory.

You can also run benchmarks individually using `ts-node` as follows:

```
$ ./node_modules/.bin/ts-node -r ./benchmarks/setup.ts ./benchmarks/benchmark-findone-mongoose.ts
{
"name": "benchmark-findone-mongoose",
"totalTimeMS": 14944
}
```

The `benchmarks/.env.benchmark` contains environment variables that configure the connection details for the benchmarks.
The `benchmarks/setup.ts` file sets up the environment using [dotenv](https://npmjs.com/package/dotenv).

## Astra Benchmarks

There are 3 benchmarks that connect to Astra, rather than local JSON API:

* `benchmark-findone-axios-vector-astra.ts`
* `benchmark-findone-mongoose-vector-astra.ts`
* `benchmark-findone-mongoose-vector-astra-http2.ts`

By default, these benchmarks are skipped:

```
$ ./node_modules/.bin/ts-node -r ./benchmarks/setup.ts ./benchmarks/benchmark-findone-mongoose-vector-astra
{"name":"benchmark-findone-mongoose-vector-astra"}
```

To run these benchmarks, you need to add the following environment variables to `.env.benchmark`:

```
ASTRA_CONNECTION_STRING=
ASTRA_COLLECTION_NAME=
```

`ASTRA_CONNECTION_STRING` contains the connection string that will be passed to `mongoose.connect()`, like `https://abc-us-east-2.apps.astra.datastax.com/api/json/v1/mykeyspace?applicationToken=AstraCS:...`, and `ASTRA_COLLECTION_NAME` is the name of the collection that the Mongoose model will connect to.
The Astra benchmarks assume that there is already a collection with data set up in Astra.

With these environment variables set up, you can run the Astra benchmarks:

```
$ ./node_modules/.bin/ts-node -r ./benchmarks/setup.ts ./benchmarks/benchmark-findone-mongoose-vector-astra
{
"name": "benchmark-findone-mongoose-vector-astra",
"totalTimeMS": 20966
}
```

If you add `ASTRA_CONNECTION_STRING` to `.env.benchmark`, be careful not to accidentally commit your changes to git.
An alternative approach is to set the environment variables in your CLI command as follows:

```
$ env ASTRA_CONNECTION_STRING="https://abc-us-east-2.apps.astra.datastax.com/..." env ASTRA_COLLECTION_NAME=mycollection ./node_modules/.bin/ts-node -r ./benchmarks/setup.ts ./benchmarks/benchmark-findone-mongoose-vector-astra
{
"name": "benchmark-findone-mongoose-vector-astra",
"totalTimeMS": 20436
}
```

## Pinecone Benchmarks

First, install the Pinecone client:

```
npm install @pinecone-database/pinecone --no-save
```

Then set up sample data:

```
```
env PINECONE_INDEX=your-index-here env PINECONE_API_KEY=your-api-key-here ./node_modules/.bin/ts-node benchmarks/setup-pinecone-vector-example.ts
```
```

Then run Pinecone benchmarks:

```
env PINECONE_INDEX=your-index-here env PINECONE_API_KEY=your-api-key-here ./node_modules/.bin/ts-node benchmarks/benchmark-findone-pinecone.ts
```
76 changes: 76 additions & 0 deletions benchmarks/benchmark-findone-axios-vector-astra.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import axios from 'axios';
import { driver } from '../';
import mongoose from 'mongoose';

mongoose.set('autoCreate', false);
mongoose.set('autoIndex', false);

mongoose.setDriver(driver);

main().then(
() => { process.exit(0); },
err => {
console.error(err);
process.exit(-1);
}
);

async function main() {
if (!process.env.ASTRA_CONNECTION_STRING) {
console.log('{"name":"benchmark-findone-axios-vector-astra"}');
return;
}
await mongoose.connect(process.env.ASTRA_CONNECTION_STRING, {
isAstra: true
} as mongoose.ConnectOptions);

const Vector = mongoose.model(
'Vector',
new mongoose.Schema({
$vector: {
type: [Number]
},
prompt: {
type: String,
required: true
}
}, {
autoCreate: false
}),
process.env.ASTRA_COLLECTION_NAME
);

// @ts-ignore
const dbName = Vector.db.db.name;

const collectionName = process.env.ASTRA_COLLECTION_NAME ?? '';

// @ts-ignore
const baseUrl = mongoose.connection.getClient().httpClient.baseUrl;

// @ts-ignore
const token = mongoose.connection.getClient().httpClient.applicationToken;
const $meta = [1, ...Array(1535).fill(0)];
const start = Date.now();
for (let i = 0; i < 100; ++i) {
await axios.post(
`${baseUrl}/${dbName}/${collectionName}`,
{
findOne: {
filter: {},
sort: { $vector: $meta }
}
},
{
headers: {
Token: token
}
}
);
}
const results = {
name: 'benchmark-findone-axios-vector-astra',
totalTimeMS: Date.now() - start
};
console.log(JSON.stringify(results, null, ' '));
}
81 changes: 81 additions & 0 deletions benchmarks/benchmark-findone-axios-vector.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
import axios from 'axios';
import { driver } from '../';
import mongoose from 'mongoose';

mongoose.set('autoCreate', false);
mongoose.set('autoIndex', false);

mongoose.setDriver(driver);

main().then(
() => { process.exit(0); },
err => {
console.error(err);
process.exit(-1);
}
);

async function main() {
await mongoose.connect(process.env.JSON_API_URI ?? '', {
username: process.env.JSON_API_USERNAME,
password: process.env.JSON_API_PASSWORD,
authUrl: process.env.JSON_API_AUTH_URL
} as mongoose.ConnectOptions);
const Vector = mongoose.model(
'Vector',
new mongoose.Schema({
$vector: {
type: [Number]
},
prompt: {
type: String,
required: true
}
}, {
collectionOptions: { vector: { size: 1536, function: 'cosine' } },

Check failure on line 35 in benchmarks/benchmark-findone-axios-vector.ts

View workflow job for this annotation

GitHub Actions / benchmarks

Type '{ size: number; function: string; }' is not assignable to type 'VectorOptions'.

Check failure on line 35 in benchmarks/benchmark-findone-axios-vector.ts

View workflow job for this annotation

GitHub Actions / benchmarks

Type '{ size: number; function: string; }' is not assignable to type 'VectorOptions'.
autoCreate: false
}),
'vectors'
);

// @ts-ignore
const dbName = Vector.db.db.name;

await Vector.db.dropCollection('vectors').catch(() => {});
await Vector.createCollection();

const numVectors = 1000;
for (let i = 0; i < numVectors; ++i) {
const $vector = Array(1536).fill(0);
$vector[i] = 1;
await Vector.create({ $vector, prompt: `Test ${i}` });
}

// @ts-ignore
const baseUrl = mongoose.connection.getClient().httpClient.baseUrl;
// @ts-ignore
const token = mongoose.connection.getClient().httpClient.applicationToken;
const $meta = [1, ...Array(1535).fill(0)];
const start = Date.now();
for (let i = 0; i < 100; ++i) {
await axios.post(
`${baseUrl}/${dbName}/vectors`,
{
findOne: {
filter: {},
sort: { $vector: $meta }
}
},
{
headers: {
Token: token
}
}
);
}
const results = {
name: 'benchmark-findone-axios-vector',
totalTimeMS: Date.now() - start
};
console.log(JSON.stringify(results, null, ' '));
}
75 changes: 75 additions & 0 deletions benchmarks/benchmark-findone-axios.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import axios from 'axios';
import { driver } from '../';
import mongoose from 'mongoose';

mongoose.set('autoCreate', false);
mongoose.set('autoIndex', false);

mongoose.setDriver(driver);

main().then(
() => { process.exit(0); },
err => {
console.error(err);
process.exit(-1);
}
);

async function main() {
const uri = process.env.JSON_API_URI ?? '';
await mongoose.connect(uri, {
username: process.env.JSON_API_USERNAME,
password: process.env.JSON_API_PASSWORD,
authUrl: process.env.JSON_API_AUTH_URL
} as mongoose.ConnectOptions);
const Test = mongoose.model('Test', new mongoose.Schema({
name: {
type: String,
required: true
},
email: {
type: String,
required: true
},
age: {
type: Number
}
}));

await Test.db.dropCollection('tests').catch(() => {});
await Test.createCollection();

await Test.create({
name: 'John Smith',
email: '[email protected]',
age: 30
});

// @ts-ignore
const token = mongoose.connection.getClient().httpClient.applicationToken;

const start = Date.now();
for (let i = 0; i < 10000; ++i) {
await axios.post(
`${uri}/tests`,
{
findOne: {
filter: {
name: 'John Smith'
},
options: {}
}
},
{
headers: {
Token: token
}
}
);
}
const results = {
name: 'benchmark-findone-axios',
totalTimeMS: Date.now() - start
};
console.log(JSON.stringify(results, null, ' '));
}
Loading
Loading