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] Issue #709: do not enqueue all responses #713

Open
wants to merge 9 commits into
base: main
Choose a base branch
from
52 changes: 52 additions & 0 deletions tests/integration/clients/test_websocket_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""Performance testing of Websocket clients."""

from __future__ import annotations

from tests.integration.integration_test_case import IntegrationTestCase
from tests.integration.it_utils import test_async_and_sync
from xrpl.models.currencies import XRP, IssuedCurrency
from xrpl.models.requests import BookOffers
from xrpl.models.response import ResponseStatus


class TestWebsocketClient(IntegrationTestCase):
"""Memory usage of websocket client"""

@test_async_and_sync(globals(), websockets_only=True)
Copy link
Collaborator

Choose a reason for hiding this comment

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

This test is against standalone, not mainnet. The data isn't going to really test anything.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Testing with a Standalone mode provides a useful baseline, because the performance will only get worse with Mainnet/Testnet.

I'm measuring the memory usage of the client when multiple successive requests are input to the client. (Since no new transactions are provided, there is no need to advance the ledger)

I can set use_testnet=True, I'm not opposed to that.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

The current integration test framework does not easily let us test against the mainnet (unless we write additional utility methods). I'm assuming you're referring to the use_testnet parameter in test_async_and_sync decorator.

Copy link
Collaborator

Choose a reason for hiding this comment

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

The integration test framework can be changed, it's not set in stone.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

are you suggesting that I test the performance against the mainnet? Why would that be different than testing with the testnet or the standalone node?

The performance of the xrpl-py client is in question, does it matter if I use a standalone/testnet/mainnet server for this test?

Copy link
Collaborator

@mvadari mvadari Jul 24, 2024

Choose a reason for hiding this comment

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

There isn't enough traffic on testnet/standalone to test the performance of xrpl-py, it's not going to run into any issues. There may not even be any data in this pair (or any pair) for the few seconds that you're testing on. You could theoretically generate that traffic yourself, but that'd require a much more complex test and I'm not sure it's worth that level of complexity.

async def test_msg_queue_growth_websocket_client(self, client):
"""Test the rate of growth of the Message queue in websocket_client under
persistent load. Admittedly, this is not a precise measure, rather its a proxy
to measure the memory footprint of the client
"""

for _ in range(5):
response = await client.request(
BookOffers(
ledger_index="current",
taker_gets=XRP(),
taker_pays=IssuedCurrency(
currency="USD", issuer="rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq"
),
limit=500,
)
)

self.assertEqual(response.status, ResponseStatus.SUCCESS)

response = await client.request(
BookOffers(
ledger_index="current",
taker_gets=IssuedCurrency(
currency="USD", issuer="rhub8VRN55s94qWKDv6jmDy1pUykJzF3wq"
),
taker_pays=XRP(),
limit=500,
)
)
self.assertEqual(response.status, ResponseStatus.SUCCESS)

self.assertEqual(client._messages.qsize(), 0)

# the messages queue has not increased in proportion to the requests/responses
# input load
self.assertEqual(client._messages.qsize(), 0)
5 changes: 2 additions & 3 deletions xrpl/asyncio/clients/websocket_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,9 +136,8 @@ async def _handler(self: Self) -> None:
# if this response corresponds to request, fulfill the Future
if "id" in response_dict and response_dict["id"] in self._open_requests:
self._open_requests[response_dict["id"]].set_result(response_dict)

# enqueue the response for the message queue
cast(_MESSAGES_TYPE, self._messages).put_nowait(response_dict)
else:
cast(_MESSAGES_TYPE, self._messages).put_nowait(response_dict)

def _set_up_future(self: Self, request: Request) -> None:
"""
Expand Down
Loading