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

Fix WebSocket threads CPU usage #88

Draft
wants to merge 1 commit into
base: 1-dev
Choose a base branch
from

Conversation

afondard
Copy link

@afondard afondard commented May 21, 2024

What does this PR do ?

This PR optimizes the WebSocket reconnection logic in the Kuzzle SDK to address high CPU usage during frequent reconnect attempts.

How should this be manually tested?

  • Step 1: Start the Kuzzle backend.
  • Step 2: Write a test Java application using the updated SDK. You can build the jar and then add the dependency in your configuration file like described below.

Maven: Add the updated SDK jar to your project’s root, then add the following dependency to your pom.xml:

        <!-- Kuzzle JVM SDK -->
        <dependency>
            <groupId>io.kuzzle</groupId>
            <artifactId>sdk-jvm</artifactId>
            <version>1.3.3</version>
            <scope>system</scope>
            <systemPath>${project.basedir}/sdk-jvm-1.3.3.jar</systemPath>
        </dependency>

Gradle: Add the updated SDK jar to your project’s lib/ folder and update your build.gradle as follows:

        // Define repository for local jars
        repositories {
            flatDir {
                dirs 'libs'
            }
        }
        
        dependencies {
            implementation name: 'sdk-jvm-1.3.3'
        }

Here's an example of a test Java main:

package kuzzle.kuzzleio;

import io.kuzzle.sdk.Kuzzle;
import io.kuzzle.sdk.coreClasses.responses.Response;
import io.kuzzle.sdk.protocol.WebSocket;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.Scanner;

public class Main {
    public static void main(String[] args) throws InterruptedException, ExecutionException {
        System.out.println("Hello world!");
        WebSocket ws = new WebSocket("localhost", 7512, false, true, 1000L);
        var kuzzle = new Kuzzle(ws);
        kuzzle.connect();
        System.out.println("Connected to Kuzzle server successfully!");

        Map<String, Object> query = new HashMap<>();
        query.put("controller", "document");
        query.put("action", "get");
        query.put("index", "tenant-asset_tracking-toto");
        query.put("collection", "devices");
        query.put("_id", "Tool-Tool1");
        Response res = kuzzle.query(query).get();
        System.out.println(res);

        Scanner scanner = new Scanner(System.in);
        System.out.println("Please enter your first name:");
        // Arrêter le back ici pour tester la queue
        String firstName = scanner.nextLine();
        System.out.println("Hello " + firstName);

        Response res2 = kuzzle.query(query).get();
        System.out.println(res2);
        // Relancer le back pour se reco et faire la requête
        System.out.println("Please enter your last name:");
        String lastName = scanner.nextLine();
        System.out.println("Last name: " + lastName);
        scanner.close();

        Response res3 = kuzzle.query(query).get();
        System.out.println(res3);
    }
}
  • Step 3 : Run the test Java application and simulate network interruptions while monitoring the CPU usage (top command for Linux).

@afondard afondard self-assigned this May 21, 2024
@afondard afondard requested a review from etrousset May 21, 2024 09:51
@afondard afondard changed the base branch from 1-dev to master May 21, 2024 10:08
@afondard afondard changed the base branch from master to 1-dev May 21, 2024 10:08
Copy link
Member

@alexandrebouthinon alexandrebouthinon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This PR break the async behaviour of the Java SDK when using the WebSocket protocol. You must revert your changes to avoid hidden breaking change on runtime. By doing this you also removed the thread safety of the SDK. I think the issue here is when reconnecting too frequently there are too much active threads. You should investigate on how to handle and clean them.

Comment on lines -117 to -123
thread(start = true) {
while (ws != null) {
val payload = queue.poll()
if (payload != null) {
GlobalScope.launch {
ws?.send(Frame.Text(payload))
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By removing the thread logic you make the SDK synchrone which is not the purpose. You should maybe handle and clean created thread when reconnecting instead of make it synchrone

@afondard afondard marked this pull request as draft May 23, 2024 07:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants