Skip to content

Commit b9ae081

Browse files
committed
Speed up cluster slot initialization
Speed up the computation for slots when initializing a cluster. After profiling, this turned out to be very slow, when it does not have to be. Do profiling a bit differently, via pytest.
1 parent a595ff7 commit b9ae081

File tree

5 files changed

+31
-28
lines changed

5 files changed

+31
-28
lines changed

.github/workflows/integration.yaml

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
pip install -r dev_requirements.txt
5555
invoke linters
5656
57-
run-tests:
57+
resp2-tests:
5858
runs-on: ubuntu-latest
5959
timeout-minutes: 60
6060
strategy:
@@ -66,7 +66,7 @@ jobs:
6666
connection-type: ['hiredis', 'plain']
6767
env:
6868
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
69-
name: Python ${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}} tests
69+
name: RESP2 ${{ matrix.python-version }} ${{matrix.test-type}}-${{matrix.connection-type}}
7070
steps:
7171
- uses: actions/checkout@v4
7272

@@ -94,7 +94,8 @@ jobs:
9494
name: pytest-results-${{matrix.test-type}}-${{matrix.connection-type}}-${{matrix.python-version}}
9595
path: |
9696
${{matrix.test-type}}*-results.xml
97-
${{matrix.test-type}}-profile.out
97+
prof/**
98+
profile_output*
9899
if-no-files-found: error
99100
retention-days: 10
100101

@@ -103,7 +104,7 @@ jobs:
103104
with:
104105
fail_ci_if_error: false
105106

106-
resp3_tests:
107+
resp3-tests:
107108
runs-on: ubuntu-latest
108109
strategy:
109110
fail-fast: false
@@ -144,7 +145,8 @@ jobs:
144145
name: pytest-results-${{matrix.test-type}}-${{matrix.connection-type}}-${{matrix.python-version}}-resp3
145146
path: |
146147
${{matrix.test-type}}*-results.xml
147-
${{matrix.test-type}}-profile.out
148+
prof/**
149+
profile_output*
148150
if-no-files-found: error
149151
retention-days: 10
150152

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,4 +16,6 @@ coverage.xml
1616
.venv*
1717
*.xml
1818
.coverage*
19+
prof
20+
profile_output*
1921
docker/stunnel/keys

dev_requirements.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ packaging>=20.4
1010
pytest
1111
pytest-asyncio
1212
pytest-cov
13+
pytest-line-profiler
14+
pytest-profiling
1315
pytest-timeout
1416
ujson>=4.2.0
1517
urllib3<2

redis/cluster.py

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,6 +1522,8 @@ def _get_or_create_cluster_node(self, host, port, role, tmp_nodes_cache):
15221522
target_node = ClusterNode(host, port, role)
15231523
if target_node.server_type != role:
15241524
target_node.server_type = role
1525+
# add this node to the nodes cache
1526+
tmp_nodes_cache[target_node.name] = target_node
15251527

15261528
return target_node
15271529

@@ -1585,31 +1587,26 @@ def initialize(self):
15851587
port = int(primary_node[1])
15861588
host, port = self.remap_host_port(host, port)
15871589

1590+
nodes_for_slot = []
1591+
15881592
target_node = self._get_or_create_cluster_node(
15891593
host, port, PRIMARY, tmp_nodes_cache
15901594
)
1591-
# add this node to the nodes cache
1592-
tmp_nodes_cache[target_node.name] = target_node
1595+
nodes_for_slot.append(target_node)
1596+
1597+
replica_nodes = [slot[j] for j in range(3, len(slot))]
1598+
for replica_node in replica_nodes:
1599+
host = str_if_bytes(replica_node[0])
1600+
port = int(replica_node[1])
1601+
host, port = self.remap_host_port(host, port)
1602+
target_replica_node = self._get_or_create_cluster_node(
1603+
host, port, REPLICA, tmp_nodes_cache
1604+
)
1605+
nodes_for_slot.append(target_replica_node)
15931606

15941607
for i in range(int(slot[0]), int(slot[1]) + 1):
15951608
if i not in tmp_slots:
1596-
tmp_slots[i] = []
1597-
tmp_slots[i].append(target_node)
1598-
replica_nodes = [slot[j] for j in range(3, len(slot))]
1599-
1600-
for replica_node in replica_nodes:
1601-
host = str_if_bytes(replica_node[0])
1602-
port = replica_node[1]
1603-
host, port = self.remap_host_port(host, port)
1604-
1605-
target_replica_node = self._get_or_create_cluster_node(
1606-
host, port, REPLICA, tmp_nodes_cache
1607-
)
1608-
tmp_slots[i].append(target_replica_node)
1609-
# add this node to the nodes cache
1610-
tmp_nodes_cache[target_replica_node.name] = (
1611-
target_replica_node
1612-
)
1609+
tmp_slots[i] = nodes_for_slot
16131610
else:
16141611
# Validate that 2 nodes want to use the same slot cache
16151612
# setup

tasks.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,11 @@ def standalone_tests(c, uvloop=False, protocol=2):
5656
"""Run tests against a standalone redis instance"""
5757
if uvloop:
5858
run(
59-
f"python -m cProfile -o standalone-profile.out -m pytest --protocol={protocol} --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --uvloop --junit-xml=standalone-uvloop-results.xml"
59+
f"pytest --profile --profile-svg --line-profile --protocol={protocol} --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --uvloop --junit-xml=standalone-uvloop-results.xml"
6060
)
6161
else:
6262
run(
63-
f"python -m cProfile -o standalone-profile.out -m pytest --protocol={protocol} --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --junit-xml=standalone-results.xml"
63+
f"pytest --profile --profile-svg --line-profile --protocol={protocol} --cov=./ --cov-report=xml:coverage_redis.xml -W always -m 'not onlycluster' --junit-xml=standalone-results.xml"
6464
)
6565

6666

@@ -70,11 +70,11 @@ def cluster_tests(c, uvloop=False, protocol=2):
7070
cluster_url = "redis://localhost:16379/0"
7171
if uvloop:
7272
run(
73-
f"python -m cProfile -o cluster-profile.out -m pytest --protocol={protocol} --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={cluster_url} --junit-xml=cluster-uvloop-results.xml --uvloop"
73+
f"pytest --profile --profile-svg --line-profile --protocol={protocol} --cov=./ --cov-report=xml:coverage_cluster.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={cluster_url} --junit-xml=cluster-uvloop-results.xml --uvloop"
7474
)
7575
else:
7676
run(
77-
f"python -m cProfile -o cluster-profile.out -m pytest --protocol={protocol} --cov=./ --cov-report=xml:coverage_clusteclient.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={cluster_url} --junit-xml=cluster-results.xml"
77+
f"pytest --profile --profile-svg --line-profile --protocol={protocol} --cov=./ --cov-report=xml:coverage_clusteclient.xml -W always -m 'not onlynoncluster and not redismod' --redis-url={cluster_url} --junit-xml=cluster-results.xml"
7878
)
7979

8080

0 commit comments

Comments
 (0)