From c560524a42f08471940567505896c41f166fc3a0 Mon Sep 17 00:00:00 2001 From: Bradley Schofield Date: Thu, 13 Feb 2025 16:52:53 +0900 Subject: [PATCH] Add more benchmarks, update DB Lib --- composer.json | 6 +- composer.lock | 80 +++++------ .../bulk-operations/LargeDocumentCreation.js | 127 ++++++++++++++++++ 3 files changed, 170 insertions(+), 43 deletions(-) create mode 100644 tests/benchmarks/bulk-operations/LargeDocumentCreation.js diff --git a/composer.json b/composer.json index dc86ab2346..3e696334b0 100644 --- a/composer.json +++ b/composer.json @@ -45,13 +45,13 @@ "ext-sockets": "*", "appwrite/php-runtimes": "0.16.*", "appwrite/php-clamav": "2.0.*", - "utopia-php/abuse": "0.49.*", + "utopia-php/abuse": "0.50.*", "utopia-php/analytics": "0.10.*", - "utopia-php/audit": "0.49.*", + "utopia-php/audit": "0.51.*", "utopia-php/cache": "0.11.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.58.4", + "utopia-php/database": "0.59.0", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index df834c4c02..6365889eea 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "53423a0249dc52d6d27bc26dc9425206", + "content-hash": "b17c58729c4380afcba7714e9bced863", "packages": [ { "name": "adhocore/jwt", @@ -3377,16 +3377,16 @@ }, { "name": "utopia-php/abuse", - "version": "0.49.0", + "version": "0.50.0", "source": { "type": "git", "url": "https://github.com/utopia-php/abuse.git", - "reference": "76612c274b895aa3d4d1fa27557a6402463eea99" + "reference": "3ff67819e9de61506c5ca070a70552f7ebe99f80" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/abuse/zipball/76612c274b895aa3d4d1fa27557a6402463eea99", - "reference": "76612c274b895aa3d4d1fa27557a6402463eea99", + "url": "https://api.github.com/repos/utopia-php/abuse/zipball/3ff67819e9de61506c5ca070a70552f7ebe99f80", + "reference": "3ff67819e9de61506c5ca070a70552f7ebe99f80", "shasum": "" }, "require": { @@ -3394,7 +3394,7 @@ "ext-pdo": "*", "ext-redis": "*", "php": ">=8.0", - "utopia-php/database": "0.58.*" + "utopia-php/database": "0.59.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3422,9 +3422,9 @@ ], "support": { "issues": "https://github.com/utopia-php/abuse/issues", - "source": "https://github.com/utopia-php/abuse/tree/0.49.0" + "source": "https://github.com/utopia-php/abuse/tree/0.50.0" }, - "time": "2025-02-04T07:33:59+00:00" + "time": "2025-02-12T09:13:59+00:00" }, { "name": "utopia-php/analytics", @@ -3474,21 +3474,21 @@ }, { "name": "utopia-php/audit", - "version": "0.49.0", + "version": "0.51.0", "source": { "type": "git", "url": "https://github.com/utopia-php/audit.git", - "reference": "9d5c5e0cf0f6d9157b911fc3971da4331d71c96d" + "reference": "a5a4b73a57e27a0fac8025b1d6038e145a1ca04e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/audit/zipball/9d5c5e0cf0f6d9157b911fc3971da4331d71c96d", - "reference": "9d5c5e0cf0f6d9157b911fc3971da4331d71c96d", + "url": "https://api.github.com/repos/utopia-php/audit/zipball/a5a4b73a57e27a0fac8025b1d6038e145a1ca04e", + "reference": "a5a4b73a57e27a0fac8025b1d6038e145a1ca04e", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/database": "0.58.*" + "utopia-php/database": "0.59.*" }, "require-dev": { "laravel/pint": "1.*", @@ -3515,9 +3515,9 @@ ], "support": { "issues": "https://github.com/utopia-php/audit/issues", - "source": "https://github.com/utopia-php/audit/tree/0.49.0" + "source": "https://github.com/utopia-php/audit/tree/0.51.0" }, - "time": "2025-02-04T07:27:18+00:00" + "time": "2025-02-12T09:12:44+00:00" }, { "name": "utopia-php/cache", @@ -3717,16 +3717,16 @@ }, { "name": "utopia-php/database", - "version": "0.58.4", + "version": "0.59.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "ff3fd22e4fe757cc2a78f17169f6dcc45c96d0fe" + "reference": "0eed7f1ad3eb66ff4a7d73b68dd9d3e05089eb18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/ff3fd22e4fe757cc2a78f17169f6dcc45c96d0fe", - "reference": "ff3fd22e4fe757cc2a78f17169f6dcc45c96d0fe", + "url": "https://api.github.com/repos/utopia-php/database/zipball/0eed7f1ad3eb66ff4a7d73b68dd9d3e05089eb18", + "reference": "0eed7f1ad3eb66ff4a7d73b68dd9d3e05089eb18", "shasum": "" }, "require": { @@ -3767,9 +3767,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.58.4" + "source": "https://github.com/utopia-php/database/tree/0.59.0" }, - "time": "2025-02-05T02:51:02+00:00" + "time": "2025-02-12T08:08:29+00:00" }, { "name": "utopia-php/domains", @@ -4170,16 +4170,16 @@ }, { "name": "utopia-php/migration", - "version": "0.6.17", + "version": "0.6.18", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "677a5c4688d7f54d1631a91f76a35d51346cf96b" + "reference": "013fe03ff17fffd80dbd3564dc1a0cdd4f4a98ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/677a5c4688d7f54d1631a91f76a35d51346cf96b", - "reference": "677a5c4688d7f54d1631a91f76a35d51346cf96b", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/013fe03ff17fffd80dbd3564dc1a0cdd4f4a98ae", + "reference": "013fe03ff17fffd80dbd3564dc1a0cdd4f4a98ae", "shasum": "" }, "require": { @@ -4187,7 +4187,7 @@ "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", - "utopia-php/database": "0.58.*", + "utopia-php/database": "0.59.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" @@ -4220,9 +4220,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.6.17" + "source": "https://github.com/utopia-php/migration/tree/0.6.18" }, - "time": "2025-02-05T05:27:29+00:00" + "time": "2025-02-12T09:09:32+00:00" }, { "name": "utopia-php/mongo", @@ -4607,16 +4607,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.8", + "version": "0.18.9", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "84737afa634e6a833fc4f8b0c967553234d3f215" + "reference": "1cf455404e8700b3093fd73d74a38d41cdced90c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/84737afa634e6a833fc4f8b0c967553234d3f215", - "reference": "84737afa634e6a833fc4f8b0c967553234d3f215", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/1cf455404e8700b3093fd73d74a38d41cdced90c", + "reference": "1cf455404e8700b3093fd73d74a38d41cdced90c", "shasum": "" }, "require": { @@ -4656,9 +4656,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.8" + "source": "https://github.com/utopia-php/storage/tree/0.18.9" }, - "time": "2024-12-04T08:30:35+00:00" + "time": "2025-02-11T13:10:40+00:00" }, { "name": "utopia-php/swoole", @@ -5560,16 +5560,16 @@ }, { "name": "myclabs/deep-copy", - "version": "1.12.1", + "version": "1.13.0", "source": { "type": "git", "url": "https://github.com/myclabs/DeepCopy.git", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845" + "reference": "024473a478be9df5fdaca2c793f2232fe788e414" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/123267b2c49fbf30d78a7b2d333f6be754b94845", - "reference": "123267b2c49fbf30d78a7b2d333f6be754b94845", + "url": "https://api.github.com/repos/myclabs/DeepCopy/zipball/024473a478be9df5fdaca2c793f2232fe788e414", + "reference": "024473a478be9df5fdaca2c793f2232fe788e414", "shasum": "" }, "require": { @@ -5608,7 +5608,7 @@ ], "support": { "issues": "https://github.com/myclabs/DeepCopy/issues", - "source": "https://github.com/myclabs/DeepCopy/tree/1.12.1" + "source": "https://github.com/myclabs/DeepCopy/tree/1.13.0" }, "funding": [ { @@ -5616,7 +5616,7 @@ "type": "tidelift" } ], - "time": "2024-11-08T17:47:46+00:00" + "time": "2025-02-12T12:17:51+00:00" }, { "name": "nikic/php-parser", diff --git a/tests/benchmarks/bulk-operations/LargeDocumentCreation.js b/tests/benchmarks/bulk-operations/LargeDocumentCreation.js new file mode 100644 index 0000000000..c903ed2dba --- /dev/null +++ b/tests/benchmarks/bulk-operations/LargeDocumentCreation.js @@ -0,0 +1,127 @@ +import { check, sleep } from "k6"; +import http from "k6/http"; +import { provisionProject, provisionDatabase, cleanup, unique } from "./utils.js"; + +const millionRecords = 1_000_000; +const batchSize = 10_000; +const numBatches = millionRecords / batchSize; + +export function setup() { + const resources = provisionProject({ + endpoint: 'http://localhost/v1', + email: 'test@test.com', + password: 'password123', + name: 'Test User', + projectName: 'Large Document Creation Test' + }); + + const { databaseId, collectionId } = provisionDatabase({ + endpoint: 'http://localhost/v1', + apiHeaders: resources.apiHeaders + }); + + // Wait to ensure that provisioning is complete + sleep(5); + + // Create an index for the collection + const index = { + key: "name", + type: "fulltext", + orders: ["ASC"], + attributes: ["name", "email"] + }; + + const indexRes = http.post(`http://localhost/v1/databases/${databaseId}/collections/${collectionId}/indexes`, + JSON.stringify(index), { + headers: resources.apiHeaders + }); + + console.log(indexRes.status); + + check(indexRes, { + "status is 202": (r) => r.status === 202, + }); + + console.log(`----- Inserting ${millionRecords} documents in ${numBatches} batches of ${batchSize} -----`); + + const timeStart = new Date(); + + const requests = []; + for (let i = 0; i < numBatches; i++) { + const docs = Array.from({ length: batchSize }, () => ({ + $id: unique(), + name: "bulk_document", + age: Math.floor(Math.random() * 100), + email: `${unique()}@test.com`, + height: Math.random() * 100 + })); + requests.push({ + method: "POST", + url: `http://localhost/v1/databases/${databaseId}/collections/${collectionId}/documents`, + body: JSON.stringify({ documents: docs }), + params: { + headers: resources.apiHeaders, + timeout: '300s' + } + }); + } + + const responses = http.batch(requests); + responses.forEach((res, index) => { + if (res.status !== 201) { + throw new Error(`Batch ${index + 1} failed with status ${res.status}`); + } + }); + + const timeEnd = new Date(); + const timeTaken = timeEnd - timeStart; + console.log(`Created 1 million documents in ${timeTaken} milliseconds`); + + return { + databaseId, + collectionId, + apiHeaders: resources.apiHeaders, + resources + }; +} + +export default function (data) { + const docs = Array.from({ length: 10000 }, () => ({ + $id: unique(), + name: "performance_document", + age: Math.floor(Math.random() * 100), + email: `${unique()}@test.com`, + height: Math.random() * 100 + })); + + const payload = JSON.stringify({ documents: docs }); + const res = http.post( + `http://localhost/v1/databases/${data.databaseId}/collections/${data.collectionId}/documents`, + payload, + { + headers: data.apiHeaders, + timeout: '300s' + } + ); + + check(res, { + "status is 201": (r) => r.status === 201 + }); + + sleep(1); +} + +export function teardown(data) { + cleanup(data.resources); +} + +export const options = { + scenarios: { + large_document_creation: { + executor: 'per-vu-iterations', + vus: 1, + iterations: 20, + exec: 'default' + } + } +}; \ No newline at end of file