From f317ba27cb27bcddc30d42fe97a06e4d099491e8 Mon Sep 17 00:00:00 2001 From: Kathiresan Selvaraj Date: Wed, 18 Dec 2024 22:54:34 -0500 Subject: [PATCH 1/4] vectorize workload changes --- ....yaml => http_jsonapi_vectorize_test.yaml} | 66 +++++++++---------- 1 file changed, 32 insertions(+), 34 deletions(-) rename nosqlbench/{http-jsonapi-vectorize-test.yaml => http_jsonapi_vectorize_test.yaml} (70%) diff --git a/nosqlbench/http-jsonapi-vectorize-test.yaml b/nosqlbench/http_jsonapi_vectorize_test.yaml similarity index 70% rename from nosqlbench/http-jsonapi-vectorize-test.yaml rename to nosqlbench/http_jsonapi_vectorize_test.yaml index c26c7cf956..b4532dbd61 100644 --- a/nosqlbench/http-jsonapi-vectorize-test.yaml +++ b/nosqlbench/http_jsonapi_vectorize_test.yaml @@ -5,12 +5,12 @@ description: >2 scenarios: default: - schema-namespace: run driver=http tags==block:schema-namespace threads==1 cycles==UNDEF - schema-collection: run driver=http tags==block:schema-collection threads==1 cycles==UNDEF - ramp-up-insert-one: run driver=http tags==name:"write.*" cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn - find-one: run driver=http tags==name:"find-one.*" cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn - find-one-update: run driver=http tags==name:"find-one-update.*" cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn - find-one-delete: run driver=http tags==name:"find-one-delete.*" cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn + #schema-namespace: run driver=http tags==block:schema-namespace threads==1 cycles==UNDEF + #schema_collection: run driver=http tags==block:schema_collection threads==1 cycles==UNDEF + ramp_up_insert_one: run driver=http tags==block:ramp_up_insert_one cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn + find_one: run driver=http tags==block:find_one cycles===TEMPLATE(write-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn + #find-one-update: run driver=http tags==name:"find-one-update.*" cycles===TEMPLATE(update-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn + #find-one-delete: run driver=http tags==name:"find-one-delete.*" cycles===TEMPLATE(delete-cycles,TEMPLATE(docscount,10000)) threads=auto errors=timer,warn bindings: # To enable an optional weighted set of hosts in place of a load balancer @@ -31,50 +31,48 @@ bindings: blocks: - schema: + schema_collection: ops: - delete-collection: +# delete_collection: +# method: POST +# uri: <>://{weighted_hosts}:<><>/v1/<> +# Accept: "application/json" +# X-Cassandra-Request-Id: "{request_id}" +# Token: "{token}" +# Content-Type: "application/json" +# ok-body: ".*\"ok\": 1.*" +# body: >2 +# { +# "deleteCollection": { +# "name": "<>" +# } +# } + create_collection: method: POST uri: <>://{weighted_hosts}:<><>/v1/<> Accept: "application/json" X-Cassandra-Request-Id: "{request_id}" Token: "{token}" Content-Type: "application/json" - ok-body: ".*\"ok\":1.*" - body: >2 - { - "deleteCollection": { - "name": "<>" - } - } - create-collection: - method: POST - uri: <>://{weighted_hosts}:<><>/v1/<> - Accept: "application/json" - X-Cassandra-Request-Id: "{request_id}" - Token: "{token}" - Content-Type: "application/json" - ok-body: ".*\"ok\":1.*" + ok-body: ".*\"ok\": 1.*" body: >2 { "createCollection": { "name" : "<>", "options": { "vector": { - "dimension": 1024 , - "metric": "cosine" - }, - "vectorize": { - "service" : "nvidia", - "options" : { - "modelName": "query" + "dimension": 2048 , + "metric": "cosine", + "service": { + "provider": "nvidia", + "modelName": "nvidia/llama-3.2-nv-embedqa-1b-v2" } } } } } - ramp-up-insert-one: + ramp_up_insert_one: ops: insert-one-vectorize: method: POST @@ -88,14 +86,14 @@ blocks: { "insertOne": { "document": { - "user_id": "{user_id}", + "movie_id": "{movie_id}", "description": "{movie_short_description}", "$vectorize": "{movie_short_description}" } } } - find-one: + find_one: ops: find-one-vectorize: method: POST @@ -108,7 +106,7 @@ blocks: body: >2 { "findOne": { - "sort" : {"$vectorize" : "{movie_short_description}"}, + "sort" : {"$vectorize" : "{movie_short_description}"} } } From c86d0fac4ddeeedc1ba20c402644de7f4a6afc64 Mon Sep 17 00:00:00 2001 From: Kathiresan Selvaraj Date: Thu, 16 Jan 2025 07:42:30 +0530 Subject: [PATCH 2/4] added cql port --- src/main/resources/application.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/application.conf b/src/main/resources/application.conf index 6826cc80a0..4fdfc397d7 100644 --- a/src/main/resources/application.conf +++ b/src/main/resources/application.conf @@ -49,6 +49,7 @@ datastax-java-driver { } } basic.request.timeout = 20 seconds + basic.contact-points = [ "10.65.0.35:29042" ] profiles { From 8fa65c4dde962415a5afe48a6629454d1aea1f92 Mon Sep 17 00:00:00 2001 From: Kathiresan Selvaraj Date: Wed, 5 Feb 2025 09:11:28 +0530 Subject: [PATCH 3/4] Insert One Performance Tests --- .../sgv2/jsonapi/InsertOnePerfTest.java | 163 ++++++++++++++++++ 1 file changed, 163 insertions(+) create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java diff --git a/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java b/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java new file mode 100644 index 0000000000..207bd62499 --- /dev/null +++ b/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java @@ -0,0 +1,163 @@ +package io.stargate.sgv2.jsonapi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class InsertOnePerfTest { + + // Base URL for the API + private static final String API_URL = System.getenv("API_URL"); + private static final String API_TOKEN = System.getenv("API_TOKEN"); + + // Number of concurrent users + private static final int NUM_USERS = 100; + + // Duration to run the simulation (in minutes) + private static final long RUN_DURATION = 10; + + // Maximum number of requests per user in the given duration (in milliseconds) + private static final long RUN_DURATION_MS = TimeUnit.MINUTES.toMillis(RUN_DURATION); + + private static final ObjectMapper objectMapper = new ObjectMapper(); // Jackson ObjectMapper + + public static void main(String[] args) { + ExecutorService executorService = Executors.newFixedThreadPool(NUM_USERS); // Limit to 200 threads + + // Get the end time (current time + 5 minutes) + long endTime = System.currentTimeMillis() + RUN_DURATION_MS; + + // Submit 200 tasks to simulate 200 users + for (int i = 1; i <= NUM_USERS; i++) { + final int userId = i; + executorService.submit(new Callable() { + @Override + public Void call() throws Exception { + try { + sendRequestsSequentially(userId, endTime); + } catch (Exception e) { + System.out.println("Error for user " + userId + ": " + e.getMessage()); + } + return null; + } + }); + } + + // Wait for all tasks to complete before shutting down executor service + try { + executorService.shutdown(); + executorService.awaitTermination(RUN_DURATION_MS + 10000, TimeUnit.MILLISECONDS); // Wait slightly longer than 5 minutes + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + System.out.println("Simulation completed."); + } + + private static void sendRequestsSequentially(int userId, long endTime) throws Exception { + // Send requests sequentially for each user as long as the 5-minute window is active + while (System.currentTimeMillis() < endTime) { + sendRequest(userId); + } + } + + private static void sendRequest(int userId) throws Exception { + URL url = new URL(API_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setRequestMethod("POST"); + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestProperty("Token", API_TOKEN); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setDoOutput(true); + + // Construct the dynamic JSON payload + String jsonPayload = buildJsonPayload(userId); + + // Write the payload to the request body + try (OutputStream os = connection.getOutputStream()) { + byte[] input = jsonPayload.getBytes("utf-8"); + os.write(input, 0, input.length); + } + + // Get the response code + int responseCode = connection.getResponseCode(); + //System.out.println("Response Code for user " + userId + ": " + responseCode); + + // If response code is 200, read and print the response body (JSON) + if (responseCode == HttpURLConnection.HTTP_OK) { + try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String inputLine; + StringBuilder response = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + + // Parse the response JSON using Jackson's ObjectMapper + JsonNode responseJson = objectMapper.readTree(response.toString()); + + // Print the response JSON + //System.out.println("Response JSON for user " + userId + ": " + responseJson.toString()); + + // Check for the "errors" field in the response + if (responseJson.has("errors")) { + System.out.println("ERROR: 'errors' field found in response for user " + userId); + System.out.println("Errors: " + responseJson.get("errors").toString()); + } + + } + } else { + // If not 200, print error message + System.out.println("Error: Received non-200 response code for user " + userId); + } + } + + private static String buildJsonPayload(int userId) { + // Build the JSON with dynamic name and random vectorize field + String name = "test_" + userId; + String vectorize = generateRandomTokens(100); + + return String.format( + "{\n" + + " \"insertOne\": {\n" + + " \"document\": {\n" + + " \"name\": \"%s\",\n" + + " \"$vectorize\": \"%s\"\n" + + " }\n" + + " }\n" + + "}", name, vectorize); + } + + private static String generateRandomTokens(int numTokens) { + // Use a random number generator for token generation + Random random = new Random(); + StringBuilder tokens = new StringBuilder(); + for (int i = 0; i < numTokens; i++) { + tokens.append(generateRandomWord(random)); + if (i < numTokens - 1) { + tokens.append(" "); // Space between tokens + } + } + return tokens.toString(); + } + + private static String generateRandomWord(Random random) { + // Generate a random word (e.g., 3-10 characters long) + int length = random.nextInt(8) + 3; + StringBuilder word = new StringBuilder(length); + for (int i = 0; i < length; i++) { + char c = (char) (random.nextInt(26) + 'a'); // Random lowercase letters + word.append(c); + } + return word.toString(); + } +} From 04950158ee5d9f3875d368d3e6d9f2d593cd9707 Mon Sep 17 00:00:00 2001 From: Kathiresan Selvaraj Date: Thu, 6 Feb 2025 08:54:16 +0530 Subject: [PATCH 4/4] Insert Many Performance Tests --- .../sgv2/jsonapi/InsertManyPerfTest.java | 166 ++++++++++++++++++ .../sgv2/jsonapi/InsertOnePerfTest.java | 163 ----------------- 2 files changed, 166 insertions(+), 163 deletions(-) create mode 100644 src/test/java/io/stargate/sgv2/jsonapi/InsertManyPerfTest.java delete mode 100644 src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java diff --git a/src/test/java/io/stargate/sgv2/jsonapi/InsertManyPerfTest.java b/src/test/java/io/stargate/sgv2/jsonapi/InsertManyPerfTest.java new file mode 100644 index 0000000000..1ba2290486 --- /dev/null +++ b/src/test/java/io/stargate/sgv2/jsonapi/InsertManyPerfTest.java @@ -0,0 +1,166 @@ +package io.stargate.sgv2.jsonapi; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.BufferedReader; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.URL; +import java.util.Random; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +public class InsertManyPerfTest { + + // Base URL for the API + private static final String API_URL = System.getenv("API_URL"); + + private static final String API_TOKEN = System.getenv("API_TOKEN"); + + // Number of concurrent users + private static final int NUM_USERS = 50; + + // Duration to run the simulation (in seconds) + private static final long RUN_DURATION_SECONDS = 10 * 60; + + // Maximum number of requests per user in the given duration (in milliseconds) + private static final long RUN_DURATION_MS = TimeUnit.SECONDS.toMillis(RUN_DURATION_SECONDS); + + private static final ObjectMapper objectMapper = new ObjectMapper(); // Jackson ObjectMapper + + public static void main(String[] args) { + ExecutorService executorService = + Executors.newFixedThreadPool(NUM_USERS); // Limit to 200 threads + + // Get the end time (current time + 5 minutes) + long endTime = System.currentTimeMillis() + RUN_DURATION_MS; + + // Submit 200 tasks to simulate 200 users + for (int i = 1; i <= NUM_USERS; i++) { + final int userId = i; + executorService.submit( + new Callable() { + @Override + public Void call() throws Exception { + try { + sendRequestsSequentially(userId, endTime); + } catch (Exception e) { + e.printStackTrace(); + System.out.println("Error for user " + userId + ": " + e.getMessage()); + } + return null; + } + }); + } + + // Wait for all tasks to complete before shutting down executor service + try { + executorService.shutdown(); + executorService.awaitTermination( + RUN_DURATION_MS + 10000, TimeUnit.MILLISECONDS); // Wait slightly longer than 5 minutes + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + } + + System.out.println("Simulation completed."); + } + + private static void sendRequestsSequentially(int userId, long endTime) throws Exception { + // Send requests sequentially for each user as long as the 5-minute window is active + while (System.currentTimeMillis() < endTime) { + sendRequest(userId); + } + } + + private static void sendRequest(int userId) throws Exception { + URL url = new URL(API_URL); + HttpURLConnection connection = (HttpURLConnection) url.openConnection(); + + connection.setRequestMethod("POST"); + connection.setRequestProperty("Accept", "application/json"); + connection.setRequestProperty("Token", API_TOKEN); + connection.setRequestProperty("Content-Type", "application/json"); + connection.setDoOutput(true); + + // Construct the dynamic JSON payload + String jsonPayload = buildJsonPayload(userId); + + // Write the payload to the request body + try (OutputStream os = connection.getOutputStream()) { + byte[] input = jsonPayload.getBytes("utf-8"); + os.write(input, 0, input.length); + } + + // Get the response code + int responseCode = connection.getResponseCode(); + // System.out.println("Response Code for user " + userId + ": " + responseCode); + + // If response code is 200, read and print the response body (JSON) + if (responseCode == HttpURLConnection.HTTP_OK) { + try (BufferedReader in = + new BufferedReader(new InputStreamReader(connection.getInputStream()))) { + String inputLine; + StringBuilder response = new StringBuilder(); + while ((inputLine = in.readLine()) != null) { + response.append(inputLine); + } + + // Parse the response JSON using Jackson's ObjectMapper + JsonNode responseJson = objectMapper.readTree(response.toString()); + + // Print the response JSON + // System.out.println("Response JSON for user " + userId + ": " + responseJson.toString()); + + // Check for the "errors" field in the response + if (responseJson.has("errors")) { + System.out.println("ERROR: 'errors' field found in response for user " + userId); + System.out.println("Errors: " + responseJson.get("errors").toString()); + } + } + } else { + // If not 200, print error message + System.out.println("Error: Received non-200 response code for user " + userId); + } + } + + private static String buildJsonPayload(int userId) { + StringBuffer sb = new StringBuffer(); + for (int i = 0; i < 50; i++) { + // Build the JSON with dynamic name and random vectorize field + String name = "test_" + userId; + String vectorize = generateRandomTokens(100); + sb.append(String.format("{\"name\": \"%s\", \"$vectorize\": \"%s\"}", name, vectorize)); + if (i < 49) { + sb.append(","); + } + } + return String.format("{\"insertMany\": {\"documents\": [%s]}}", sb); + } + + private static String generateRandomTokens(int numTokens) { + // Use a random number generator for token generation + Random random = new Random(); + StringBuilder tokens = new StringBuilder(); + for (int i = 0; i < numTokens; i++) { + tokens.append(generateRandomWord(random)); + if (i < numTokens - 1) { + tokens.append(" "); // Space between tokens + } + } + return tokens.toString(); + } + + private static String generateRandomWord(Random random) { + // Generate a random word (e.g., 3-10 characters long) + int length = random.nextInt(8) + 3; + StringBuilder word = new StringBuilder(length); + for (int i = 0; i < length; i++) { + char c = (char) (random.nextInt(26) + 'a'); // Random lowercase letters + word.append(c); + } + return word.toString(); + } +} diff --git a/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java b/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java deleted file mode 100644 index 207bd62499..0000000000 --- a/src/test/java/io/stargate/sgv2/jsonapi/InsertOnePerfTest.java +++ /dev/null @@ -1,163 +0,0 @@ -package io.stargate.sgv2.jsonapi; - -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectMapper; -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.URL; -import java.util.Random; -import java.util.concurrent.Callable; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; - -public class InsertOnePerfTest { - - // Base URL for the API - private static final String API_URL = System.getenv("API_URL"); - private static final String API_TOKEN = System.getenv("API_TOKEN"); - - // Number of concurrent users - private static final int NUM_USERS = 100; - - // Duration to run the simulation (in minutes) - private static final long RUN_DURATION = 10; - - // Maximum number of requests per user in the given duration (in milliseconds) - private static final long RUN_DURATION_MS = TimeUnit.MINUTES.toMillis(RUN_DURATION); - - private static final ObjectMapper objectMapper = new ObjectMapper(); // Jackson ObjectMapper - - public static void main(String[] args) { - ExecutorService executorService = Executors.newFixedThreadPool(NUM_USERS); // Limit to 200 threads - - // Get the end time (current time + 5 minutes) - long endTime = System.currentTimeMillis() + RUN_DURATION_MS; - - // Submit 200 tasks to simulate 200 users - for (int i = 1; i <= NUM_USERS; i++) { - final int userId = i; - executorService.submit(new Callable() { - @Override - public Void call() throws Exception { - try { - sendRequestsSequentially(userId, endTime); - } catch (Exception e) { - System.out.println("Error for user " + userId + ": " + e.getMessage()); - } - return null; - } - }); - } - - // Wait for all tasks to complete before shutting down executor service - try { - executorService.shutdown(); - executorService.awaitTermination(RUN_DURATION_MS + 10000, TimeUnit.MILLISECONDS); // Wait slightly longer than 5 minutes - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - } - - System.out.println("Simulation completed."); - } - - private static void sendRequestsSequentially(int userId, long endTime) throws Exception { - // Send requests sequentially for each user as long as the 5-minute window is active - while (System.currentTimeMillis() < endTime) { - sendRequest(userId); - } - } - - private static void sendRequest(int userId) throws Exception { - URL url = new URL(API_URL); - HttpURLConnection connection = (HttpURLConnection) url.openConnection(); - - connection.setRequestMethod("POST"); - connection.setRequestProperty("Accept", "application/json"); - connection.setRequestProperty("Token", API_TOKEN); - connection.setRequestProperty("Content-Type", "application/json"); - connection.setDoOutput(true); - - // Construct the dynamic JSON payload - String jsonPayload = buildJsonPayload(userId); - - // Write the payload to the request body - try (OutputStream os = connection.getOutputStream()) { - byte[] input = jsonPayload.getBytes("utf-8"); - os.write(input, 0, input.length); - } - - // Get the response code - int responseCode = connection.getResponseCode(); - //System.out.println("Response Code for user " + userId + ": " + responseCode); - - // If response code is 200, read and print the response body (JSON) - if (responseCode == HttpURLConnection.HTTP_OK) { - try (BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()))) { - String inputLine; - StringBuilder response = new StringBuilder(); - while ((inputLine = in.readLine()) != null) { - response.append(inputLine); - } - - // Parse the response JSON using Jackson's ObjectMapper - JsonNode responseJson = objectMapper.readTree(response.toString()); - - // Print the response JSON - //System.out.println("Response JSON for user " + userId + ": " + responseJson.toString()); - - // Check for the "errors" field in the response - if (responseJson.has("errors")) { - System.out.println("ERROR: 'errors' field found in response for user " + userId); - System.out.println("Errors: " + responseJson.get("errors").toString()); - } - - } - } else { - // If not 200, print error message - System.out.println("Error: Received non-200 response code for user " + userId); - } - } - - private static String buildJsonPayload(int userId) { - // Build the JSON with dynamic name and random vectorize field - String name = "test_" + userId; - String vectorize = generateRandomTokens(100); - - return String.format( - "{\n" + - " \"insertOne\": {\n" + - " \"document\": {\n" + - " \"name\": \"%s\",\n" + - " \"$vectorize\": \"%s\"\n" + - " }\n" + - " }\n" + - "}", name, vectorize); - } - - private static String generateRandomTokens(int numTokens) { - // Use a random number generator for token generation - Random random = new Random(); - StringBuilder tokens = new StringBuilder(); - for (int i = 0; i < numTokens; i++) { - tokens.append(generateRandomWord(random)); - if (i < numTokens - 1) { - tokens.append(" "); // Space between tokens - } - } - return tokens.toString(); - } - - private static String generateRandomWord(Random random) { - // Generate a random word (e.g., 3-10 characters long) - int length = random.nextInt(8) + 3; - StringBuilder word = new StringBuilder(length); - for (int i = 0; i < length; i++) { - char c = (char) (random.nextInt(26) + 'a'); // Random lowercase letters - word.append(c); - } - return word.toString(); - } -}