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

TopologyComparators performance issue #1011

Closed
alessandrosimi-sa opened this issue Apr 9, 2019 · 2 comments
Closed

TopologyComparators performance issue #1011

alessandrosimi-sa opened this issue Apr 9, 2019 · 2 comments
Labels
type: feature A new feature
Milestone

Comments

@alessandrosimi-sa
Copy link
Contributor

Bug Report

Current Behavior

The essentiallyEqualsTo method of the TopologyComparators has a performance issue due to the comparison between the slots. With an aggressive cluster topology refresh interval (500ms) and a single node cluster the machine spends the majority of the CPU on the the essentiallyEqualsTo method and in specific on the o1.getSlots().containsAll(o2.getSlots()) code.

Input Code

I created a this simple class to reproduce the error. In my machine this code takes around 11 seconds.

package io.lettuce.core.cluster.topology;

import io.lettuce.core.cluster.SlotHash;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode;

import java.util.ArrayList;
import java.util.List;

public class SlowTest {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        RedisClusterNode nodeA = createNode();
        RedisClusterNode nodeB = createNode();
        for (int i = 0; i < 100; i++) nodeA.getSlots().containsAll(nodeB.getSlots());
        System.out.println(System.currentTimeMillis() - start);
    }

    private static RedisClusterNode createNode() {
        RedisClusterNode nodeA = new RedisClusterNode();
        List<Integer> slots = new ArrayList<>();
        for (int i = 0; i < SlotHash.SLOT_COUNT; i++) {
            slots.add(i);
        }
        nodeA.setSlots(slots);
        return nodeA;
    }
    
}

Expected behavior/code

The comparison should be faster so the cluster topology can be refreshed without impacting the performance of the application.

Environment

  • Lettuce version(s): latest (tested on 5.2.0.BUILD-SNAPSHOT)
  • Redis version: -

Possible Solution

The equals method of the BitSet should be equivalent so it can be used as alternative.

public boolean hasSameSlotsOf(RedisClusterNode node) {
    if (node == null) return false;
    else return this.slots.equals(node.slots);
}

This method can be part of the RedisClusterNode class.

The test with the new method takes 20~ ms on my machine.

package io.lettuce.core.cluster.topology;

import io.lettuce.core.cluster.SlotHash;
import io.lettuce.core.cluster.models.partitions.RedisClusterNode;

import java.util.ArrayList;
import java.util.List;

public class SlowTest {

    public static void main(String[] args) {
        long start = System.currentTimeMillis();
        RedisClusterNode nodeA = createNode();
        RedisClusterNode nodeB = createNode();
        for (int i = 0; i < 100; i++) nodeA.hasSameSlotsOf(nodeB); // <-- here I'm using the new method
        System.out.println(System.currentTimeMillis() - start);
    }

    private static RedisClusterNode createNode() {
        RedisClusterNode nodeA = new RedisClusterNode();
        List<Integer> slots = new ArrayList<>();
        for (int i = 0; i < SlotHash.SLOT_COUNT; i++) {
            slots.add(i);
        }
        nodeA.setSlots(slots);
        return nodeA;
    }

}
@mp911de mp911de added the type: feature A new feature label Apr 10, 2019
@mp911de
Copy link
Collaborator

mp911de commented Apr 10, 2019

Thanks for reporting the issue. Care to submit a pull request?

mp911de pushed a commit that referenced this issue Apr 11, 2019
We now use BitSet.equals() to compare slot sets of RedisClusterNode for an improved comparison performance.

Original pull request: #1013.
mp911de added a commit that referenced this issue Apr 11, 2019
Refactor nullability check as RedisClusterNode is expected to be never null. Add author tags.

Original pull request: #1013
mp911de pushed a commit that referenced this issue Apr 11, 2019
We now use BitSet.equals() to compare slot sets of RedisClusterNode for an improved comparison performance.

Original pull request: #1013.
mp911de added a commit that referenced this issue Apr 11, 2019
Refactor nullability check as RedisClusterNode is expected to be never null. Add author tags.

Original pull request: #1013
@mp911de mp911de added this to the 5.1.7 milestone Apr 11, 2019
@mp911de
Copy link
Collaborator

mp911de commented Apr 11, 2019

Thanks a lot for your contribution! That's fixed now.

@mp911de mp911de closed this as completed Apr 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature A new feature
Projects
None yet
Development

No branches or pull requests

2 participants