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

Performance tests for Python get/set sequence #41

Merged
merged 6 commits into from
Jul 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions test/python/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,3 +114,13 @@ def one_use_output(one_use_connector):
@pytest.fixture
def one_use_input(one_use_connector):
return one_use_connector.get_input("MySubscriber::MySquareReader")

def pytest_addoption(parser):
parser.addoption("--iterations", action="store", default=100)

def pytest_generate_tests(metafunc):
# This is called for every test. Only get/set command line arguments
# if the argument is specified in the list of test "fixturenames".
option_value = metafunc.config.option.iterations
if 'iterations' in metafunc.fixturenames and option_value is not None:
metafunc.parametrize("iterations", [int(option_value)])
105 changes: 105 additions & 0 deletions test/python/test_rticonnextdds_performance.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
###############################################################################
# (c) 2020 Copyright, Real-Time Innovations. All rights reserved. #
# No duplications, whole or partial, manual or electronic, may be made #
# without express written permission. Any such copies, or revisions thereof, #
# must display this notice unaltered. #
# This code contains trade secrets of Real-Time Innovations, Inc. #
###############################################################################

import pytest,sys,os
sys.path.append(os.path.dirname(os.path.realpath(__file__))+ "/../../")
import rticonnextdds_connector as rti
from test_utils import *

# iterations is configured by passing `--iterations <>` on the command line.
# By default, pytest captures the stdout. Supply -s to view the results.

# These tests currently take around 25 minutes to run with 100 iterations.
# They were added to help verify performance of another product, connextdds-py.
# If you want to run them, remove this decorator.
# Maybe once CON-42 is implemented we can run them by default.
@pytest.mark.skip(reason="Takes too long to run these tests, remove this line and run manually")
class TestPerformance:
"""
This class tests the performance of Connector
"""

# The use-case of setting a sequence in Connector is slow, and likely will
# be until we implement CON-42.
# Here we time how long it takes to set a sequence element by element.
def test_set_sequence_element_by_element(self, one_use_connector, iterations):
# Get the input and output which communicate using the performance test type
the_input = one_use_connector.get_input("MySubscriber::PerformanceTestReader")
the_output = one_use_connector.get_output("MyPublisher::PerformanceTestWriter")

# Wait for discovery between the entities
the_input.wait_for_publications(5000)
the_output.wait_for_subscriptions(5000)

# Set each element of the sequence separately
total_time = 0
for i in range(0, iterations):
start_time = time.time()
for i in range (0, 600000):
the_output.instance['myOctSeq[%d]' % (i)] = 2
total_time += (time.time() - start_time)
average_time = total_time / iterations
print("Average time setting element-by-element: " + str(average_time))
# Average time setting element-by-element: 2.9646800351142883

# The use-case of setting a sequence in Connector is slow, and likely will
# be until we implement CON-42.
# Here we time how long it takes to set a sequence from a Python list.
# i.e., output.instance['myOctSeq'] = [1, 2, 3, 4, 5, ....]
def test_set_sequence_from_list(self, one_use_connector, iterations):
# Get the input and output which communicate using the performance test type
the_input = one_use_connector.get_input("MySubscriber::PerformanceTestReader")
the_output = one_use_connector.get_output("MyPublisher::PerformanceTestWriter")

# Wait for discovery between the entities
the_input.wait_for_publications(5000)
the_output.wait_for_subscriptions(5000)

# Create a python list which contains 600000 and set the sequence from it
total_time = 0
average_time = 0
myOctSeq = [0]
for i in range (1, 600000):
myOctSeq.append(i)

for i in range (0, iterations):
start_time = time.time()
the_output.instance['myOctSeq'] = myOctSeq
total_time += (time.time() - start_time)
average_time = total_time / iterations
print("Average time setting entire list in one go: " + str(average_time))
# Note to self Average time: 6.60276771068573

# The use-case of obtaining a dictionary containing a sequence in Connector
# is slow, and likely will be until we implement CON-42.
# Here we have a sequence with 600000 elements. We time how long it takes to
# obtain this sequence as a Python list
def test_get_sequence(self, one_use_connector, iterations):
# Get the input and output which communicate using the performance test type
the_input = one_use_connector.get_input("MySubscriber::PerformanceTestReader")
the_output = one_use_connector.get_output("MyPublisher::PerformanceTestWriter")

# Wait for discovery between the entities
the_input.wait_for_publications(5000)
the_output.wait_for_subscriptions(5000)
# Set the sample on the writer (the performance of this operation is tested
# in the test_set_sequence test)
the_output.instance['myOctSeq[599999]'] = 2
# Write the sample and receive it on the input
sample = send_data(the_output, the_input)

# Now we can test the performance. We time how long it takes to retrieve the
# sequence as a dictionary, repeat x times and take the average
total_time = 0
for i in range (0, iterations):
start_time = time.time()
myOctSeq = sample['myOctSeq']
total_time += (time.time() - start_time)
average_time = total_time / iterations
print("Average time to get sequence as a list: " + str(average_time))
# Note to self Average time: 0.20733366489410401
25 changes: 24 additions & 1 deletion test/xml/TestConnector.xml
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,11 @@ This code contains trade secrets of Real-Time Innovations, Inc.
<struct name="ShapeTypeWithoutToplevelKeyType">
<member name="unkeyed_shape" type="nonBasic" nonBasicTypeName="ShapeType"/>
<member name="keyed_shape" type="nonBasic" nonBasicTypeName="ShapeType" key="true"/>
</struct>
</struct>
<struct name="PerformanceTestType" extensibility="extensible">
<member name='myID' type="long"/>
<member name="myOctSeq" type="byte" sequenceMaxLength="600000"/>
</struct>
</types>

<!-- Domain Library -->
Expand All @@ -176,6 +180,7 @@ This code contains trade secrets of Real-Time Innovations, Inc.
<register_type name="NestedKeyedShapeType" type_ref="NestedKeyedShapeType"/>
<register_type name="UnboundedType" type_ref="UnboundedType" />
<register_type name="ShapeTypeWithoutToplevelKeyType" type_ref="ShapeTypeWithoutToplevelKeyType" />
<register_type name="PerformanceTestType" type_ref="PerformanceTestType" />
<topic name="UnkeyedSquare" register_type_ref="UnkeyedShapeType"/>
<topic name="MultipleKeyedSquare" register_type_ref="MultipleKeyedShapeType"/>
<topic name="NestedKeyedSquare" register_type_ref="NestedKeyedShapeType"/>
Expand All @@ -184,6 +189,7 @@ This code contains trade secrets of Real-Time Innovations, Inc.
<topic name="SingleUseShape" register_type_ref="ShapeType"/>
<topic name="UnboundedTopic" register_type_ref="UnboundedType"/>
<topic name="ShapeTypeWithoutToplevelKey" register_type_ref="ShapeTypeWithoutToplevelKeyType"/>
<topic name="PerformanceTopic" register_type_ref="PerformanceTestType"/>
</domain>
<domain name="DataAccessDomain" domain_id="0">
<register_type name="MyType" type_ref="MyType" />
Expand Down Expand Up @@ -218,6 +224,22 @@ This code contains trade secrets of Real-Time Innovations, Inc.
<data_writer name="MyMultipleKeyedSquareWriter" topic_ref="MultipleKeyedSquare"/>
<data_writer name="MyNestedKeyedSquareWriter" topic_ref="NestedKeyedSquare"/>
<data_writer name="MySquareWithoutTopLevelKeyWriter" topic_ref="ShapeTypeWithoutToplevelKey"/>
<data_writer name="PerformanceTestWriter" topic_ref="PerformanceTopic">
<datawriter_qos>
<reliability>
<kind> RELIABLE_RELIABILITY_QOS </kind>
</reliability>
<history>
<kind> KEEP_ALL_HISTORY_QOS </kind>
</history>
<durability>
<kind> TRANSIENT_LOCAL_DURABILITY_QOS </kind>
</durability>
<publish_mode>
<kind>ASYNCHRONOUS_PUBLISH_MODE_QOS</kind>
</publish_mode>
</datawriter_qos>
</data_writer>
</publisher>

<subscriber name="MySubscriber">
Expand All @@ -226,6 +248,7 @@ This code contains trade secrets of Real-Time Innovations, Inc.
<data_reader name="MyMultipleKeyedSquareReader" topic_ref="MultipleKeyedSquare" />
<data_reader name="MyNestedKeyedSquareReader" topic_ref="NestedKeyedSquare" />
<data_reader name="MySquareWithoutTopLevelKeyReader" topic_ref="ShapeTypeWithoutToplevelKey" />
<data_reader name="PerformanceTestReader" topic_ref="PerformanceTopic" />
</subscriber>
</domain_participant>

Expand Down