1.3.3. RTI Persistence Service
1.3.3.1. Unkeyed, UDPv4 10Gbps Network
The graph below shows the one-way latency without load between a Publisher and a Subscriber running in two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
We use the median (50th percentile) instead of the average in order to get a more stable measurement that does not account for spurious outliers. We also calculate the average value and other percentile values, which can be seen in the Detailed Statistics section below.
Detailed Statistics
The following tables contain the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the latency tables and plots:
- Avg: Mean of the avg values for N runs per sample size.
- Std: Standard deviation of the avg values across N runs. High values suggest inconsistency across runs.
- Plot representation: for each sample size, all N individual values are plotted as circles. The line connects the average of the N values (‘Avg’ in the table) across all sample sizes.
Sample Size |
Avg |
P-50 |
Std |
Min |
Max |
P-99 |
P-9999 |
|---|---|---|---|---|---|---|---|
32 |
16.99 |
16.8 |
1.11 |
16.03 |
87.25 |
19.69 |
48.51 |
256 |
18 |
17.59 |
6.01 |
16.77 |
4944 |
30.97 |
54.41 |
512 |
20.3 |
19.72 |
3.19 |
17.44 |
116.47 |
37.03 |
62.63 |
1024 |
26.02 |
26.48 |
12.33 |
18.45 |
4748.38 |
45.47 |
74.71 |
8192 |
44.88 |
39.51 |
13.6 |
36.21 |
4703.96 |
79.11 |
123.24 |
63000 |
187.54 |
187.56 |
2.5 |
121.29 |
221.98 |
191.42 |
200.03 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the expected throughput behavior when performing a 1-1 communication between two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
The throughput results shown in this section were obtained with a test environment tuned for reproducibility.
The setup uses Ubuntu with real-time extensions enabled, explicit CPU affinity pinning,
deterministic thread priorities, and a tuned profile focused on jitter reduction.
Detailed Statistics
This table contains the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the throughput tables and plots:
- Avg Mbps: Average throughput of N tests in megabits per second.
- Std (Mbps): Standard deviation of the throughput across N tests. High values suggest inconsistency across test executions.
- Plot representation: for each sample size, all N individual throughput values are plotted as points. The line connects the average of the N values for each sample size across all sample sizes.
Sample Size (bytes) |
Avg Mbps |
Avg Samples/s |
Lost Samples |
Lost Samples (%) |
|---|---|---|---|---|
32 |
28.6 |
111561 |
0 |
0 |
256 |
225.1 |
109903 |
0 |
0 |
512 |
446 |
108898 |
0 |
0 |
4096 |
3310.5 |
101029 |
0 |
0 |
8192 |
6245.3 |
95295 |
0 |
0 |
63000 |
9416 |
18682 |
0 |
0 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the one-way latency without load between a Publisher and a Subscriber running in two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
We use the median (50th percentile) instead of the average in order to get a more stable measurement that does not account for spurious outliers. We also calculate the average value and other percentile values, which can be seen in the Detailed Statistics section below.
Detailed Statistics
The following tables contain the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the latency tables and plots:
- Avg: Mean of the avg values for N runs per sample size.
- Std: Standard deviation of the avg values across N runs. High values suggest inconsistency across runs.
- Plot representation: for each sample size, all N individual values are plotted as circles. The line connects the average of the N values (‘Avg’ in the table) across all sample sizes.
Sample Size |
Avg |
P-50 |
Std |
Min |
Max |
P-99 |
P-9999 |
|---|---|---|---|---|---|---|---|
32 |
168.99 |
104.89 |
443.77 |
97.88 |
8458.42 |
3319.57 |
6425.56 |
256 |
176.56 |
108.03 |
465.93 |
101.57 |
10508.86 |
3366.86 |
6486.75 |
512 |
185.25 |
111.58 |
488.95 |
103.57 |
11392.83 |
3456.26 |
7227.67 |
1024 |
203.16 |
120.41 |
517.77 |
108.64 |
10442.19 |
3525.47 |
7150.76 |
8192 |
341.58 |
198.09 |
754.41 |
170.99 |
11461.24 |
4812.33 |
8565.91 |
63000 |
1258.36 |
642.88 |
2303.2 |
344.18 |
26732.58 |
13069.98 |
19950.59 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the expected throughput behavior when performing a 1-1 communication between two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
The throughput results shown in this section were obtained with a test environment tuned for reproducibility.
The setup uses Ubuntu with real-time extensions enabled, explicit CPU affinity pinning,
deterministic thread priorities, and a tuned profile focused on jitter reduction.
Detailed Statistics
This table contains the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the throughput tables and plots:
- Avg Mbps: Average throughput of N tests in megabits per second.
- Std (Mbps): Standard deviation of the throughput across N tests. High values suggest inconsistency across test executions.
- Plot representation: for each sample size, all N individual throughput values are plotted as points. The line connects the average of the N values for each sample size across all sample sizes.
Sample Size (bytes) |
Avg Mbps |
Avg Samples/s |
Lost Samples |
Lost Samples (%) |
|---|---|---|---|---|
32 |
1.6 |
6099 |
0 |
0 |
256 |
12 |
5869 |
0 |
0 |
512 |
22.6 |
5521 |
0 |
0 |
4096 |
115.5 |
3525 |
0 |
0 |
8192 |
186 |
2838 |
0 |
0 |
63000 |
292.2 |
579 |
0 |
0 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the one-way latency without load between a Publisher and a Subscriber running in two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
We use the median (50th percentile) instead of the average in order to get a more stable measurement that does not account for spurious outliers. We also calculate the average value and other percentile values, which can be seen in the Detailed Statistics section below.
Detailed Statistics
The following tables contain the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the latency tables and plots:
- Avg: Mean of the avg values for N runs per sample size.
- Std: Standard deviation of the avg values across N runs. High values suggest inconsistency across runs.
- Plot representation: for each sample size, all N individual values are plotted as circles. The line connects the average of the N values (‘Avg’ in the table) across all sample sizes.
Sample Size |
Avg |
P-50 |
Std |
Min |
Max |
P-99 |
P-9999 |
|---|---|---|---|---|---|---|---|
32 |
19.44 |
19.11 |
1.54 |
18.2 |
85.46 |
25.49 |
54.33 |
256 |
20.13 |
19.66 |
2.47 |
18.68 |
92.81 |
33.94 |
61.38 |
512 |
20.89 |
20.32 |
2.55 |
19.26 |
83.9 |
31.6 |
63.47 |
1024 |
26.82 |
26.46 |
7.37 |
20.07 |
3401.84 |
40.41 |
76.16 |
8192 |
46.35 |
41.05 |
9.95 |
38.54 |
788.71 |
84.75 |
125.25 |
63000 |
189.71 |
189.69 |
2.11 |
118.09 |
221.89 |
193.82 |
201.62 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the expected throughput behavior when performing a 1-1 communication between two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
The throughput results shown in this section were obtained with a test environment tuned for reproducibility.
The setup uses Ubuntu with real-time extensions enabled, explicit CPU affinity pinning,
deterministic thread priorities, and a tuned profile focused on jitter reduction.
Detailed Statistics
This table contains the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the throughput tables and plots:
- Avg Mbps: Average throughput of N tests in megabits per second.
- Std (Mbps): Standard deviation of the throughput across N tests. High values suggest inconsistency across test executions.
- Plot representation: for each sample size, all N individual throughput values are plotted as points. The line connects the average of the N values for each sample size across all sample sizes.
Sample Size (bytes) |
Avg Mbps |
Avg Samples/s |
Lost Samples |
Lost Samples (%) |
|---|---|---|---|---|
32 |
26.2 |
102281 |
0 |
0 |
256 |
206.7 |
100932 |
0 |
0 |
512 |
410.7 |
100270 |
0 |
0 |
4096 |
3104.8 |
94752 |
0 |
0 |
8192 |
5768.8 |
88024 |
0 |
0 |
63000 |
9445 |
18740 |
0 |
0 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the one-way latency without load between a Publisher and a Subscriber running in two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
We use the median (50th percentile) instead of the average in order to get a more stable measurement that does not account for spurious outliers. We also calculate the average value and other percentile values, which can be seen in the Detailed Statistics section below.
Detailed Statistics
The following tables contain the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the latency tables and plots:
- Avg: Mean of the avg values for N runs per sample size.
- Std: Standard deviation of the avg values across N runs. High values suggest inconsistency across runs.
- Plot representation: for each sample size, all N individual values are plotted as circles. The line connects the average of the N values (‘Avg’ in the table) across all sample sizes.
Sample Size |
Avg |
P-50 |
Std |
Min |
Max |
P-99 |
P-9999 |
|---|---|---|---|---|---|---|---|
32 |
238.91 |
120.53 |
835.11 |
113.78 |
15337.96 |
3757.21 |
12039.69 |
256 |
250.6 |
125.83 |
848.22 |
116.37 |
13746.58 |
4135.23 |
12914.75 |
512 |
252.53 |
130.3 |
827.35 |
119.34 |
15628.32 |
3762.66 |
11871.98 |
1024 |
269.12 |
137.22 |
839.88 |
125.03 |
17545.53 |
3982.12 |
11929.75 |
8192 |
411.52 |
216.47 |
1007.31 |
193.37 |
14404.03 |
6056.39 |
12441.08 |
63000 |
1329.28 |
660.88 |
2356.61 |
382.72 |
20632.12 |
12414.49 |
20221.71 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)
The graph below shows the expected throughput behavior when performing a 1-1 communication between two Linux nodes in a 10Gbps network. The numbers are for best-effort as well as strict reliable reliability scenarios.
Note
The throughput results shown in this section were obtained with a test environment tuned for reproducibility.
The setup uses Ubuntu with real-time extensions enabled, explicit CPU affinity pinning,
deterministic thread priorities, and a tuned profile focused on jitter reduction.
Detailed Statistics
This table contains the raw numbers presented by RTI Perftest. These numbers are the exact output with no further processing.
Reliable
How to read the throughput tables and plots:
- Avg Mbps: Average throughput of N tests in megabits per second.
- Std (Mbps): Standard deviation of the throughput across N tests. High values suggest inconsistency across test executions.
- Plot representation: for each sample size, all N individual throughput values are plotted as points. The line connects the average of the N values for each sample size across all sample sizes.
Sample Size (bytes) |
Avg Mbps |
Avg Samples/s |
Lost Samples |
Lost Samples (%) |
|---|---|---|---|---|
32 |
1.1 |
4288 |
0 |
0 |
256 |
8.5 |
4163 |
0 |
0 |
512 |
16.2 |
3955 |
0 |
0 |
4096 |
90.9 |
2773 |
0 |
0 |
8192 |
154.4 |
2355 |
0 |
0 |
63000 |
278 |
551 |
0 |
0 |
Perftest Scripts
To produce these tests, we executed RTI Perftest for C++98 and Persistence Service. The exact script used can be found here:
1#!/bin/bash
2filename=$0
3
4# This is in order to know where is the script and where is the repo base folder
5script_location=$(cd "$(dirname "$filename")" || exit 255; pwd)
6repo_location=`cd "$script_location/../.."; pwd`
7
8################################################################################
9
10# We will use some colors to improve visibility of errors and information
11RED='\033[0;31m'
12GREEN='\033[0;32m'
13YELLOW='\033[0;33m'
14NC='\033[0m'
15INFO_TAG="${GREEN}[INFO]:${NC}"
16WARNING_TAG="${YELLOW}[WARNING]:${NC}"
17ERROR_TAG="${RED}[ERROR]:${NC}"
18
19# Use key-based SSH only and fail fast instead of prompting for a password.
20export ssh="ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -o LogLevel=ERROR -o BatchMode=yes -o PreferredAuthentications=publickey -o PasswordAuthentication=no -o KbdInteractiveAuthentication=no -o NumberOfPasswordPrompts=0 -o ConnectTimeout=8 -o ConnectionAttempts=1"
21
22################################################################################
23
24# Default Lab to use.
25export LAB="LINUX_X64"
26
27# TEST RELATED CONSTANTS
28
29# Some default values for certain variables like openssl
30export openssl_1_version="openssl-1.1.1s"
31export openssl_3_version="openssl-3.0.12"
32export openssl_309_version="openssl-3.0.9"
33export openssl_3011_version="openssl-3.0.11"
34export openssl_350_version="openssl-3.5.0"
35export openssl_355_version="openssl-3.5.5"
36export wolfssl_version="wolfssl-5.5.1"
37export JAVA_LINUX_BIN_PATH="/local/apps/Java/PLATFORMSDK/linux64/jdk-11.0.7+10/bin"
38export DOTNET6_LINUX_BIN_PATH="/local/apps/dotnet/dotnet-sdk-5.0.103-linux-x64"
39
40export middleware="pro"
41export TEST_KIND="throughput"
42export KEYED_UNKEYED="unkeyed"
43export MULTICAST_UNICAST="unicast"
44export timeout_value=200
45export machines_to_use=""
46
47################################################################################
48### FUNCTIONS
49
50### Cleaning funtion:
51
52function clean_machines () {
53
54 if ! validate_ssh_connectivity_all_machines; then
55 echo -e "$ERROR_TAG Aborting cleanup due to SSH connectivity failures."
56 return 1
57 fi
58
59 echo -e "${YELLOW}Clean Machines${NC}: Launching cleanup in parallel for ${number_machines} machine(s)..."
60
61 for ((i = 0 ; i < number_machines ; i++)); do
62 (
63 $ssh "${machines[$i]}" pkill perftest_cpp >/dev/null 2>&1 || true
64 # stdout and stderr in tcsh to /dev/null
65 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
66
67 if [[ "${machines[$i]}" == "$tcpdump_machine" && "$TCP_DUMP" == "1" ]]; then
68 $ssh "${machines[$i]}" sudo pkill tcpdump >/dev/null 2>&1 || true
69 fi
70 ) &
71 done
72 wait
73
74 echo -e "${YELLOW}Clean Machines${NC}: Base cleanup ${GREEN}Done.${NC}"
75
76 if [[ "$PERSISTENCE_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$ROUTING_SERVICE" == "1" ]]; then
77 echo -e "${YELLOW}Clean Machines${NC}: Cleaning infrastructure services in parallel..."
78 for ((i = 0 ; i < number_machines ; i++)); do
79 (
80 $ssh "${machines[$i]}" pkill rtipersistenc >/dev/null 2>&1 || true
81 $ssh "${machines[$i]}" pkill rtirecording >/dev/null 2>&1 || true
82 $ssh "${machines[$i]}" pkill rtirouting >/dev/null 2>&1 || true
83 # stdout and stderr in tcsh to /dev/null
84 $ssh "${machines[$i]}" killall -s KILL /bin/bash >/dev/null 2>&1 || true
85 ) &
86 done
87 wait
88 echo -e "${YELLOW}Clean Machines${NC}: Infrastructure services cleanup ${GREEN}Done.${NC}"
89
90 fi
91 if [[ "${THR_LAT_MODE}" == "THR" ]]; then
92 for ((i = 0 ; i < number_machines ; i++)); do
93 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_thr_mode.sh &"
94 $ssh "${machines[$i]}" sudo /set_thr_mode.sh &
95 done
96 # Wait for all the background processes to finish
97 wait
98 elif [[ "${THR_LAT_MODE}" == "LAT" ]]; then
99 for ((i = 0 ; i < $number_machines ; i++)); do
100 echo -e "$INFO_TAG ssh ${machines[$i]} sudo /set_lat_mode.sh &"
101 $ssh "${machines[$i]}" sudo /set_lat_mode.sh &
102 done
103 # Wait for all the background processes to finish
104 wait
105 fi
106}
107
108### Reboot Machines:
109
110function reboot_machines () {
111 for ((i = 0 ; i < $number_machines ; i++)); do
112 command="$ssh ${machines[$i]} sudo reboot"
113 echo -e "$INFO_TAG Executing $command"
114 $command
115 done
116}
117
118
119# trap ctrl-c and call ctrl_c()
120trap 'ctrl_c' SIGINT
121
122function ctrl_c() {
123 echo -e " ${RED}TRAPPED CTRL-C !!!!!!!!!!! ${NC}"
124 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
125 killall -s KILL /bin/bash
126}
127
128### Check if I can access via SSH to a machine
129
130function check_ssh_machine() {
131 command="$ssh $1 exit"
132 $command
133 if [[ "$?" == "0" ]]; then
134 echo "true"
135 else
136 echo "false"
137 fi
138}
139
140function validate_ssh_connectivity_all_machines() {
141 local failed_machines=()
142 local failed_machines_file
143 failed_machines_file=$(mktemp)
144
145 echo -e "$INFO_TAG Checking SSH connectivity for all selected machines..."
146 for ((i = 0 ; i < number_machines ; i++)); do
147 (
148 if [[ "$(check_ssh_machine "${machines[$i]}")" != "true" ]]; then
149 echo "${machines[$i]}" >> "$failed_machines_file"
150 fi
151 ) &
152 done
153 wait
154
155 while IFS= read -r failed_machine; do
156 failed_machines+=("$failed_machine")
157 done < "$failed_machines_file"
158 rm -f "$failed_machines_file"
159
160 if [[ "${#failed_machines[@]}" -gt 0 ]]; then
161 echo -e "$ERROR_TAG SSH connectivity check failed for:"
162 for machine in "${failed_machines[@]}"; do
163 echo -e " - ${machine}"
164 done
165 return 1
166 fi
167
168 echo -e "$INFO_TAG SSH connectivity check passed."
169 return 0
170}
171
172function append_ld_library_path_export() {
173 local script_file=$1
174 local lib_path=$2
175
176 if [[ "$NO_LD_PATH_CHECKS" == "1" ]]; then
177 echo -e "export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH;" >> "$script_file"
178 else
179 echo -e "if [[ -d \"${lib_path}\" ]]; then export LD_LIBRARY_PATH=${lib_path}:\$LD_LIBRARY_PATH; fi" >> "$script_file"
180 fi
181}
182
183### Calculate the perftest executable name and check if exists
184
185function calculate_perftest_binary() {
186 if [[ "$LANGUAGE" == "c++98" ]]; then
187 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp"
188 elif [[ "$LANGUAGE" == "c++11" ]]; then
189 export perftest_exec="${PERFTESTHOME}/bin/${PLATFORM}/${RELEASE_DEBUG}/perftest_cpp11"
190 elif [[ "$LANGUAGE" == "java" ]]; then
191 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_java.sh"
192 elif [[ "$LANGUAGE" == "cs" ]]; then
193 export perftest_exec="${PERFTESTHOME}/bin/${RELEASE_DEBUG}/perftest_cs"
194 fi
195
196 if [[ ! -f $perftest_exec ]]; then
197 echo -e "$ERROR_TAG: The Perftest binary does not exist: $perftest_exec"
198 exit -1
199 fi
200
201 if [[ "$RECORDING_SERVICE" == "1" ]]; then
202 export recording_wrapper_exec="${PERFTESTHOME}/resource/recording_service/recordingservice_wrapper.sh"
203 fi
204
205 if [[ "$ROUTING_SERVICE" == "1" ]]; then
206 export routing_service_exec="${PERFTESTHOME}/resource/routing_service/routingservice_wrapper.sh"
207 fi
208
209 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
210 export persistence_service_exec="${PERFTESTHOME}/resource/persistence_service/persistenceService_wrapper.sh"
211 fi
212
213}
214
215### Calculate the folder where to store the results
216
217function calculate_store_folder() {
218
219 export store_point="${PERFTESTNUMBERSHOME}/results/${middleware}/${BRANCH}/network_performance/core/${LANGUAGE}/${TRANSPORT}"
220}
221
222calculate_store_folder
223
224################################################################################
225
226while [ "$1" != "" ]; do
227 case $1 in
228 --nddshome)
229 export NDDSHOME=$2
230 shift
231 ;;
232 --perftest-home)
233 export PERFTESTHOME=$2
234 shift
235 ;;
236 --perftest-numbers-home)
237 export PERFTESTNUMBERSHOME=$2
238 shift
239 ;;
240 --transport)
241 export TRANSPORT=$2
242 shift
243 ;;
244 --arch1 | --platform)
245 export PLATFORM=$2
246 shift
247 ;;
248 --arch2)
249 export ARCH2=$2
250 shift
251 ;;
252 --branch)
253 export BRANCH=$2
254 shift
255 ;;
256 --id)
257 export BUILD_ID=$2
258 shift
259 ;;
260 --openssl-libs)
261 export OPENSSLPATHLIB=$2
262 shift
263 ;;
264 --multicast)
265 export MULTICAST_UNICAST="multicast"
266 ;;
267 --unicast)
268 export MULTICAST_UNICAST="unicast"
269 ;;
270 --best-effort | --be)
271 export BEST_EFFORT="1"
272 ;;
273 --reliable | --rel)
274 export BEST_EFFORT=""
275 ;;
276 --num-publishers)
277 export publishers=$2
278 shift
279 ;;
280 --num-subscribers)
281 export subscribers=$2
282 shift
283 ;;
284 --output-folder)
285 export results_output=$2
286 shift
287 ;;
288 --execution-time)
289 export execution_time=$2
290 shift
291 ;;
292 --data-length | --datalen)
293 export datalen=$2
294 shift
295 ;;
296 --dry)
297 export DRY=1
298 ;;
299 --clean)
300 export CLEAN_MACHINES=1
301 ;;
302 --reboot)
303 reboot_machines
304 exit 0
305 ;;
306 --thr-mode)
307 export THR_LAT_MODE="THR"
308 ;;
309 --lat-mode)
310 export THR_LAT_MODE="LAT"
311 ;;
312 --leave-pub-alone)
313 export PUB_ALONE=1
314 ;;
315 --no-positive-acks)
316 export NO_POS_ACKS=1
317 ;;
318 --security-gov)
319 export SECURITY=1
320 ;;
321 --cft)
322 export CFT=1
323 ;;
324 --instances)
325 export INSTANCES=$2
326 shift
327 ;;
328 --latency-test | --latency)
329 export TEST_KIND="latency"
330 ;;
331 --throughput)
332 export TEST_KIND="throughput"
333 ;;
334 --keyed)
335 export KEYED_UNKEYED="keyed"
336 ;;
337 --unkeyed)
338 export KEYED_UNKEYED="unkeyed"
339 ;;
340 --batch-size)
341 export BATCH_SIZE=$2
342 shift
343 ;;
344 --routing-service)
345 export ROUTING_SERVICE=1
346 ;;
347 --recording-service)
348 export RECORDING_SERVICE=1
349 ;;
350 --persistence-service | --ps)
351 export PERSISTENCE_SERVICE=1
352 ;;
353 --domain-pub)
354 export DOMAIN_PUB=$2
355 shift
356 ;;
357 --domain-sub)
358 export DOMAIN_SUB=$2
359 shift
360 ;;
361 --domain-rec)
362 export DOMAIN_REC=$2
363 shift
364 ;;
365 --domain-rs)
366 export DOMAIN_RS=$2
367 shift
368 ;;
369 --domain-ps)
370 export DOMAIN_PS=$2
371 shift
372 ;;
373 --timeout)
374 export timeout_value=$2
375 shift
376 ;;
377 --durability)
378 export DURABILITY=$2
379 shift
380 ;;
381 --ps-no-direct-communication)
382 export NO_DIRECT_COMMUNICATION=1
383 ;;
384 --test-name)
385 export test_name=$2
386 shift
387 ;;
388 --lab | --lab-file)
389 export LAB_FILE=$2
390 shift
391 ;;
392 --lab-folder)
393 export LAB_FILE="$2/lab.json"
394 shift
395 ;;
396 --machines)
397 export machines_to_use=$2
398 shift
399 ;;
400 --low-jitter-settings)
401 export low_jitter_settings="1"
402 ;;
403 --no-ld-path-checks)
404 export NO_LD_PATH_CHECKS="1"
405 ;;
406 --taskset)
407 export TASKSET_LIST=$2
408 shift
409 ;;
410 *)
411 echo -e "unknown parameter \"$1\""
412 exit -1
413 ;;
414 esac
415 shift
416done
417
418################################################################################
419
420function validate_input() {
421
422
423 if [[ "$LAB_FILE" != "" ]]; then
424 if [ -f "$LAB_FILE" ]; then
425 echo -e "$INFO_TAG Loading lab file $LAB_FILE"
426 export machines=($(jq -r 'to_entries[] | .key' "$LAB_FILE"))
427 export main_interface=($(jq -r 'to_entries[] | .value.main_interface.interface' $LAB_FILE))
428 export main_interface_ip=($(jq -r 'to_entries[] | .value.main_interface.ip' $LAB_FILE))
429 export platforms=($(jq -r 'to_entries[] | .value.architecture' $LAB_FILE))
430 export number_machines=${#machines[@]}
431
432 if [[ "$machines_to_use" != "" ]]; then
433 if ! [[ "$machines_to_use" =~ ^[0-9]+$ ]]; then
434 echo -e "$ERROR_TAG: --machines must be a positive integer."
435 exit -1
436 fi
437
438 if [[ "$machines_to_use" -lt "2" ]]; then
439 echo -e "$ERROR_TAG: --machines must be >= 2."
440 exit -1
441 fi
442
443 if [[ "$machines_to_use" -gt "$number_machines" ]]; then
444 echo -e "$ERROR_TAG: --machines ($machines_to_use) cannot be greater than machines in lab file ($number_machines)."
445 exit -1
446 fi
447
448 machines=("${machines[@]:0:$machines_to_use}")
449 main_interface=("${main_interface[@]:0:$machines_to_use}")
450 main_interface_ip=("${main_interface_ip[@]:0:$machines_to_use}")
451 platforms=("${platforms[@]:0:$machines_to_use}")
452 export number_machines=${#machines[@]}
453 fi
454
455 else
456 echo -e "$ERROR_TAG: The lab file $lab_file does not exist."
457 exit -1
458 fi
459 fi
460
461 if [[ "$CLEAN_MACHINES" == "1" ]]; then
462 if ! clean_machines; then
463 exit -1
464 fi
465 exit 0
466 fi
467
468 # Lets fill up the test information first, either with the defaults or the data.
469
470 if [[ "$PERFTESTNUMBERSHOME" == "" ]]; then
471 export PERFTESTNUMBERSHOME=$repo_location
472 fi
473
474 if [[ "$PERFTESTHOME" == "" ]]; then
475 echo -e "$ERROR_TAG: We need a perftest home"
476 exit -1
477 elif [ ! -d "$PERFTESTHOME" ]; then
478 echo -e "$ERROR_TAG: The Perftest home $PERFTESTHOME does not exist."
479 exit -1
480 fi
481
482 if [[ "$NDDSHOME" == "" ]]; then
483 echo "Setting NDDSHOME to PERFTESTHOME"
484 export NDDSHOME=$PERFTESTHOME
485 fi
486
487 if [[ "$TRANSPORT" == "" ]]; then
488 export TRANSPORT="UDPv4_10Gbps"
489 fi
490
491 if [[ "$LANGUAGE" == "" ]]; then
492 export LANGUAGE="c++98"
493 fi
494
495 if [[ "$RELEASE_DEBUG" == "" ]]; then
496 export RELEASE_DEBUG="release"
497 fi
498
499 if [[ "$PLATFORM" == "" ]]; then
500 export PLATFORM="x64Linux4gcc8.5.0"
501 fi
502
503 if [[ "$ARCH2" != "" ]]; then
504 echo -e "$WARNING_TAG: --arch2 will be ignored and $PLATFORM will be used instead"
505 fi
506 export ARCH2=$PLATFORM
507
508 if [[ "$OPENSSLPATHLIB" == "" ]]; then
509 export OPENSSL1PATHLIB="${NDDSHOME}/third_party/${openssl_1_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
510 export OPENSSL3PATHLIB="${NDDSHOME}/third_party/${openssl_3_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
511 export OPENSSL3011PATHLIB="${NDDSHOME}/third_party/${openssl_3011_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
512 export OPENSSL309PATHLIB="${NDDSHOME}/third_party/${openssl_309_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
513 export OPENSSL350PATHLIB="${NDDSHOME}/third_party/${openssl_350_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
514 export OPENSSL355PATHLIB="${NDDSHOME}/third_party/${openssl_355_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
515 export WOLFSSLPATH_LIB="${NDDSHOME}/third_party/${wolfssl_version}/${PLATFORM}/${RELEASE_DEBUG}/lib"
516 fi
517
518 if [[ "$BEST_EFFORT" == "1" ]]; then
519 export BEST_EFFORT=" -best "
520 export be_string="be"
521 else
522 export be_string="rel"
523 fi
524
525 calculate_perftest_binary
526 calculate_store_folder
527
528 if [[ "$TASKSET_LIST" != "" ]]; then
529 export taskset_prefix="taskset -c $TASKSET_LIST"
530 else
531 export taskset_prefix=""
532 fi
533
534 if [[ "$publishers" == "" ]]; then
535 export publishers=1
536 fi
537
538 if [[ "$subscribers" == "" ]]; then
539 export subscribers=1
540 fi
541
542 if [[ "${MULTICAST_UNICAST}" == "multicast" ]]; then
543 export USE_MULTICAST="-multicast"
544 fi
545 if [[ "$results_output" == "" ]]; then
546 export results_output="${repo_location}/results/pro/${BRANCH}/${BUILD_ID}/network_performance"
547
548 if [[ "$ROUTING_SERVICE" == "1" ]]; then
549 export results_output="${results_output}/infrastructure_services/routing_service"
550 elif [[ "$RECORDING_SERVICE" == "1" ]]; then
551 export results_output="${results_output}/infrastructure_services/recording_service"
552 elif [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
553 export ps_communication_mode="direct"
554 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
555 export ps_communication_mode="no_direct"
556 fi
557 export results_output="${results_output}/infrastructure_services/persistence_service/${ps_communication_mode}"
558 else
559 export results_output="${results_output}/core/${LANGUAGE}/N-M"
560 fi
561
562 export results_output="${results_output}/${TEST_KIND}/${be_string}/${KEYED_UNKEYED}/${MULTICAST_UNICAST}"
563 fi
564
565 if [[ "$execution_time" == "" ]]; then
566 export execution_time=30
567 fi
568
569 if [[ "$datalen" == "" ]]; then
570 export datalen=100
571 fi
572
573 if [[ "$NO_POS_ACKS" == "1" ]]; then
574 export no_positive_acks="-noPositiveAcks"
575 export results_output="${results_output}_no_positive_acks"
576 fi
577
578 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
579 export keyed_args="-keyed"
580 fi
581
582 if [[ "$INSTANCES" != "" ]]; then
583 export instances_args="-instances $INSTANCES"
584 elif [[ "$KEYED_UNKEYED" == "keyed" ]]; then
585 export instances_args="-instances 200"
586 fi
587
588 if [[ "$CFT" != "" ]]; then
589 export results_output="${results_output}_cft"
590 fi
591
592 export LAT_THR_SCRIPT="/set_thr_mode.sh"
593 export latency_count="-latencyCount 10000"
594 if [[ "$TEST_KIND" == "latency" ]]; then
595 export latency_test="-latencyTest"
596 export latency_count=""
597 export LAT_THR_SCRIPT="/set_lat_mode.sh"
598 fi
599
600 if [[ "$CFT" == "1" ]]; then
601 export instances_args="-instances $subscribers"
602 fi
603
604 export PATH_TO_GOVERNANCE_FILES_FOLDER=$PERFTESTHOME/resource/secure
605
606 if [[ "$SECURITY" == "1" ]]; then
607 export security_params="-secureGovernanceFile $PATH_TO_GOVERNANCE_FILES_FOLDER/signed_PerftestGovernance_RTPSEncrypt.xml"
608 fi
609
610 echo -e "$INFO_TAG: TEST INFO:\n"
611 echo -e " - Perftest home = $PERFTESTHOME"
612 echo -e " - Number of machines = $number_machines"
613 echo -e " - Number of publishers = $publishers"
614 echo -e " - Number of subscribers = $subscribers"
615 echo -e " - OpenSSL Libraries path = $OPENSSLPATHLIB $OPENSSL1PATHLIB $OPENSSL3PATHLIB"
616
617 echo
618
619 export full_test_name="${TRANSPORT}_${be_string}_${publishers}_${subscribers}_${number_machines}"
620 if [[ "$test_name" != "" ]]; then
621 export full_test_name="${test_name}"
622 return
623 fi
624
625}
626
627function main() {
628
629 echo -e "\n=== LAUNCHING PERFORMANCE TESTS ===\n"
630
631 # This function will fill up the environmental variables needed to test
632 validate_input
633
634 export temporal_output=$repo_location/.test/output
635 export temporal_output_files=$repo_location/.test/output_files
636 export temporal_scripts=$repo_location/.test/generated_scripts
637 rm -rf ${temporal_scripts}/*
638 rm -rf ${temporal_output}/*
639 rm -rf ${temporal_output_files}/*
640 mkdir -p $temporal_output
641 mkdir -p $temporal_output_files
642 mkdir -p $temporal_scripts
643 mkdir -p $results_output
644
645 echo -e "\n$INFO_TAG: Cleaning machines before starting the test:"
646 if ! clean_machines; then
647 exit -1
648 fi
649
650 # Generate scripts to run for every perftest
651
652 echo -e "\n$INFO_TAG: GENERATING SCRIPTS:"
653 for ((i = 0 ; i < $number_machines ; i++)); do
654 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
655 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
656 echo "Creating $script_file"
657 touch $script_file
658 chmod +x $script_file
659 echo -e "#!/bin/bash" >> $script_file
660 if [[ "$THR_LAT_MODE" != "" && "$low_jitter_settings" != "1" ]]; then
661 echo -e "sudo $LAT_THR_SCRIPT" >> $script_file
662 echo -e "sleep 5;" >> $script_file
663 fi
664 echo -e "cd $PERFTESTHOME;" >> $script_file
665 echo -e "export NDDSHOME=${NDDSHOME};" >> $script_file
666 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}"
667 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-1.1.1"
668 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.0"
669 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/openssl-3.5"
670 append_ld_library_path_export "$script_file" "${NDDSHOME}/lib/${PLATFORM}/wolfssl-5.5"
671 if [[ "$OPENSSLPATHLIB" == "" ]]; then
672 append_ld_library_path_export "$script_file" "${OPENSSL1PATHLIB}"
673 append_ld_library_path_export "$script_file" "${OPENSSL3PATHLIB}"
674 append_ld_library_path_export "$script_file" "${OPENSSL309PATHLIB}"
675 append_ld_library_path_export "$script_file" "${OPENSSL3011PATHLIB}"
676 append_ld_library_path_export "$script_file" "${OPENSSL350PATHLIB}"
677 append_ld_library_path_export "$script_file" "${OPENSSL355PATHLIB}"
678 append_ld_library_path_export "$script_file" "${WOLFSSLPATH_LIB}"
679 else
680 append_ld_library_path_export "$script_file" "${OPENSSLPATHLIB}"
681 fi
682 echo -e "export PERFTEST_BIN=${perftest_exec};" >> $script_file
683
684 if [[ "$RECORDING_SERVICE" == "1" ]]; then
685 echo -e "export RECORDING_WRAPPER=${recording_wrapper_exec};" >> $script_file
686 fi
687
688 if [[ "$ROUTING_SERVICE" == "1" ]]; then
689 echo -e "export ROUTING_WRAPPER=${routing_service_exec};" >> $script_file
690 fi
691
692 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
693 echo -e "export PERSISTENCE_SERVICE_WRAPPER=${persistence_service_exec};" >> $script_file
694 fi
695
696 echo -e "touch ${output_file} \\" >> $script_file
697 done
698 echo -e ""
699
700 if [[ "$PUB_ALONE" == "1" ]]; then
701 if [[ "$publishers" -gt "1" ]]; then
702 echo -e "$ERROR_TAG: If you want to have the publisher alone, you can only have one"
703 exit -1
704 fi
705 fi
706
707 for ((i = 0 ; i < $number_machines ; i++)); do
708 machine_status[$i]="None"
709 done
710
711 carried_index=0
712 for ((i = 0 ; i < $publishers ; i++)); do
713 index=$(($i%$number_machines))
714 # echo "i is $i -- index $index"
715 carried_index=$i
716 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
717 temporal_ouput_file_stderr="${temporal_output_files}/stderr_pub_${full_test_name}_${machines[$index]}_$i.txt"
718 temporal_ouput_file_stout="${temporal_output_files}/stdout_pub_${full_test_name}_${machines[$index]}_$i.csv"
719 export no_headers="-noOutputHeaders"
720 if [[ "$NO_POS_ACKS" == "1" ]]; then
721 export no_positive_acks_string="${no_positive_acks} -initialBurst 80000"
722 fi
723 if [[ "${DOMAIN_PUB}" != "" ]]; then
724 export domain_pub="-domain ${DOMAIN_PUB}"
725 fi
726 if [[ "$DURABILITY" != "" ]]; then
727 export durability="-durability $DURABILITY"
728 fi
729 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
730 export no_direct_communication="-noDirectCommunication"
731 fi
732 if [[ "$BATCH_SIZE" != "" ]]; then
733 export batch_size="-batchSize $BATCH_SIZE"
734 fi
735
736 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -pub -datalen $datalen ${latency_test} ${cft_related_params_pub} \
737 ${keyed_args} ${instances_args} ${domain_pub} ${durability} ${no_direct_communication} ${batch_size} \
738 -transport UDPv4 -nic ${main_interface[$index]} -pid $i -numSubscribers $subscribers ${security_params} \
739 -exec $execution_time ${latency_count} -noPrint -noXML ${no_positive_acks_string} ${USE_MULTICAST} \
740 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
741 machine_status[$carried_index]="Perftest Publisher"
742 echo -e "&" >> $script_file
743 echo $command >> $script_file
744 done
745
746 carried_index=$(($carried_index+1))
747 for ((i = 0 ; i < $subscribers ; i++)); do
748 carried_i=$(($i+$carried_index))
749 index=$(( ($i+$carried_index) % ($number_machines-1) ))
750 index=$(($index+1))
751 # echo "i is $carried_i -- index $index"
752 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
753 temporal_ouput_file_stderr="${temporal_output_files}/stderr_sub_${full_test_name}_${machines[$index]}_$i.txt"
754 temporal_ouput_file_stout="${temporal_output_files}/stdout_sub_${full_test_name}_${machines[$index]}_$i.csv"
755 export no_headers="-noOutputHeaders"
756 if [[ "${DOMAIN_SUB}" != "" ]]; then
757 export domain_sub="-domain ${DOMAIN_SUB}"
758 fi
759 if [[ "$CFT" == "1" ]]; then
760 export cft_related_params_sub="-cft $i:$i"
761 fi
762 if [[ "$DURABILITY" != "" ]]; then
763 export durability="-durability $DURABILITY"
764 fi
765 if [[ "$NO_DIRECT_COMMUNICATION" == "1" ]]; then
766 export no_direct_communication="-noDirectCommunication"
767 fi
768 export command="${taskset_prefix} \$PERFTEST_BIN $no_headers -sub -transport UDPv4 -nic ${main_interface[$index]} -sid $i ${cft_related_params_sub} \
769 ${keyed_args} ${instances_args} ${domain_sub} ${durability} ${no_direct_communication} \
770 -numPublishers $publishers -noPrint ${security_params} -noXML ${USE_MULTICAST} ${no_positive_acks} \
771 ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
772 machine_status[$index]="Perftest Subscriber"
773 echo -e "&" >> $script_file
774 echo $command >> $script_file
775 done
776
777 if [[ "$RECORDING_SERVICE" == "1" ]]; then
778 carried_index=$(($carried_index+1))
779 for ((i = 0 ; i < 1 ; i++)); do
780 carried_i=$(($i+$carried_index))
781 index=$(( ($i+$carried_index) % ($number_machines-1) ))
782 index=$(($index+1))
783 # echo "i is $carried_i -- index $index"
784 if [[ "${DOMAIN_REC}" != "" ]]; then
785 export domain_recs="-domain ${DOMAIN_REC}"
786 fi
787 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
788 export keyed_args="-keyed"
789 fi
790 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
791 temporal_ouput_file_stderr="${temporal_output_files}/stderr_recording_${full_test_name}_${machines[$index]}_$i.txt"
792 temporal_ouput_file_stout="${temporal_output_files}/stdout_recording_${full_test_name}_${machines[$index]}_$i.csv"
793 execution_time_recording=$(($execution_time+20))
794 export command="\$RECORDING_WRAPPER -executionTime $execution_time_recording -nic ${main_interface[$index]} $domain_recs \
795 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
796 echo -e "&" >> $script_file
797 echo $command >> $script_file
798 machine_status[$index]="recording"
799 done
800 fi
801
802 if [[ "$ROUTING_SERVICE" == "1" ]]; then
803 carried_index=$(($carried_index+1))
804 for ((i = 0 ; i < 1 ; i++)); do
805 carried_i=$(($i+$carried_index))
806 index=$(( ($i+$carried_index) % ($number_machines-1) ))
807 index=$(($index+1))
808 # echo "i is $carried_i -- index $index"
809 if [[ "${DOMAIN_RS}" != "" ]]; then
810 export domain_rs="-domain ${DOMAIN_RS}"
811 fi
812 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
813 export keyed_args="-keyed"
814 fi
815 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
816 temporal_ouput_file_stderr="${temporal_output_files}/stderr_routing_${full_test_name}_${machines[$index]}_$i.txt"
817 temporal_ouput_file_stout="${temporal_output_files}/stdout_routing_${full_test_name}_${machines[$index]}_$i.csv"
818 execution_time_routing=$(($execution_time+40))
819 export command="\$ROUTING_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_rs \
820 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
821 echo -e "&" >> $script_file
822 echo $command >> $script_file
823 machine_status[$index]="routing"
824 done
825 fi
826
827
828 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
829 carried_index=$(($carried_index+1))
830 for ((i = 0 ; i < 1 ; i++)); do
831 carried_i=$(($i+$carried_index))
832 index=$(( ($i+$carried_index) % ($number_machines-1) ))
833 index=$(($index+1))
834 if [[ "${DOMAIN_PS}" != "" ]]; then
835 export domain_ps="-domain ${DOMAIN_PS}"
836 fi
837 if [[ "$KEYED_UNKEYED" == "keyed" ]]; then
838 export keyed_args="-keyed"
839 fi
840 export script_file="${temporal_scripts}/${full_test_name}_${machines[$index]}.sh"
841 temporal_ouput_file_stderr="${temporal_output_files}/stderr_ps_${full_test_name}_${machines[$index]}_$i.txt"
842 temporal_ouput_file_stout="${temporal_output_files}/stdout_ps_${full_test_name}_${machines[$index]}_$i.csv"
843 execution_time_routing=$(($execution_time+40))
844 export command="\$PERSISTENCE_SERVICE_WRAPPER -executionTime $execution_time_routing -nic ${main_interface[$index]} $domain_ps \
845 ${keyed_args} ${BEST_EFFORT} 2>${temporal_ouput_file_stderr} 1>${temporal_ouput_file_stout} \\"
846 echo -e "&" >> $script_file
847 echo $command >> $script_file
848 machine_status[$index]="persistence"
849 done
850 fi
851
852 for ((i = 0 ; i < $number_machines ; i++)); do
853 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
854 output_file="${temporal_output}/${full_test_name}_${machines[$i]}.txt"
855 echo -e ";" >> $script_file
856 echo ${output_file}
857 echo -e "echo -e \"FINISHED $?\" >> ${output_file}" >> $script_file
858 echo -e "echo \"${machines[$i]} OK [${machine_status[$i]}]\"" >> $script_file
859 done
860
861 # If using dry we do not execute anything
862 if [[ "$DRY" == "1" ]]; then
863 echo -e "\n$WARNING_TAG Dry test, leaving now, scripts are written.\n"
864 exit 0
865 fi
866
867 echo -e "\n$INFO_TAG: LAUNCHING TEST:"
868 # ssh to each of the machines executing the command!
869 for ((i = 0 ; i < $number_machines ; i++)); do
870 script_file="${temporal_scripts}/${full_test_name}_${machines[$i]}.sh"
871 export ssh_command="$ssh ${machines[$i]} \"${script_file}\" &"
872 echo -e $ssh_command
873
874 $ssh ${machines[$i]} "${script_file}" &
875 done
876 echo -e "\n"
877
878 sleep 5
879 echo -e "\n$INFO_TAG Test started!!! $full_test_name"
880
881 # Every machine will write a file in $script_location/output, with a single
882 # file, once they finish, if the number of lines is = to the number of participants
883 # that means discovery was completed.
884 sleep 1
885 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
886 sleep 5
887 i=5
888 while [ "$found" != "$number_machines" ]; do
889 ((i=i+10))
890 sleep 10
891 echo -e "${GREEN}TEST: $full_test_name ${NC} -- Time: $i s (Found = $found, waiting for $number_machines)."
892 export found=`cat ${temporal_output}/${full_test_name}_*.txt | wc -l`
893 if [[ "$i" -gt "$timeout_value" ]]; then
894 echo -e "$ERROR_TAG: Timeout"
895 clean_machines || echo -e "$WARNING_TAG Cleanup skipped due to SSH connectivity failures."
896 exit 111
897 fi
898 done
899 sleep 2
900
901 # rm -rf "${results_output}/pub"
902 # rm -rf "${results_output}/subs"
903 mkdir -p "${results_output}/pub"
904 mkdir -p "${results_output}/subs"
905 export result_file_pubs="${results_output}/pub/${full_test_name}.csv"
906 export result_file_subs="${results_output}/subs/${full_test_name}.csv"
907 touch $result_file_pubs
908 touch $result_file_subs
909
910 echo "Sample Size (Bytes), Ave (μs), Std (μs), Min (μs), Max (μs), 50% (μs), 90% (μs), 99% (μs), 99.99% (μs), 99.9999% (μs)" >> $result_file_pubs
911 echo "Sample Size (Bytes), Total Samples, Avg Samples/s, Avg Mbps, Lost Samples, Lost Samples (%)" >> $result_file_subs
912 echo -e "$INFO_TAG: Result files are in : $result_file_pubs"
913 cat $temporal_output_files/stdout_pub* >> $result_file_pubs
914 cat $temporal_output_files/stdout_sub* >> $result_file_subs
915
916 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_pubs" > "${result_file_pubs}.tmp" && mv "${result_file_pubs}.tmp" "$result_file_pubs"
917 awk 'NR==1 {print $0 ", command-line"; next} {print $0 ",command-line not provided"}' "$result_file_subs" > "${result_file_subs}.tmp" && mv "${result_file_subs}.tmp" "$result_file_subs"
918
919 if [[ "$RECORDING_SERVICE" == "1" ]]; then
920 rm -rf "${results_output}/recording"
921 mkdir -p "${results_output}/recording"
922 export result_file_recording="${results_output}/recording/${full_test_name}.csv"
923 touch $result_file_recording
924 cat $temporal_output_files/stdout_recording* >> $result_file_recording
925 fi
926
927 if [[ "$ROUTING_SERVICE" == "1" ]]; then
928 rm -rf "${results_output}/routing"
929 mkdir -p "${results_output}/routing"
930 export result_file_routing="${results_output}/routing/${full_test_name}.csv"
931 touch $result_file_routing
932 cat $temporal_output_files/stdout_routing* >> $result_file_routing
933 fi
934
935 if [[ "$PERSISTENCE_SERVICE" == "1" ]]; then
936 rm -rf "${results_output}/persistence"
937 mkdir -p "${results_output}/persistence"
938 export result_file_persistence="${results_output}/persistence/${full_test_name}.csv"
939 touch $result_file_persistence
940 cat $temporal_output_files/stdout_ps* >> $result_file_persistence
941 fi
942
943 # Merge infrastructure services results into consolidated CSV files
944 if [[ "$ROUTING_SERVICE" == "1" || "$RECORDING_SERVICE" == "1" || "$PERSISTENCE_SERVICE" == "1" ]]; then
945 echo -e "$INFO_TAG Merging infrastructure services results..."
946 export merge_script="${repo_location}/scripts/tools/merge_infrastructure_services_results.py"
947 if [[ -f "$merge_script" ]]; then
948 python3 "$merge_script" "${results_output}"
949 else
950 echo -e "$WARNING_TAG Merge script not found: $merge_script"
951 fi
952 fi
953
954 echo -e "$INFO_TAG Test finished Successfully"
955
956}
957
958main
Test Software
The following software was used to perform these tests:
RTI Connext DDS 7.7.0 Host and Target Libraries for x64 Linux (x64Linux4gcc8.5.0)
Test Hardware
The following hardware was used to perform these tests:
Linux Nodes
Dell R340 Servers (13 Units)
Processor: Intel Xeon E-2278G (3.4-5GHz, 8c/16t, 16MB cache, 2 memory channels @2666MHz)
RAM: 4x 16GB 2666MHz DIMM (64GB RAM)
HD: 480GB SATA SSD
NIC 1: Intel 710 dual port 10Gbps SFP
OS: Ubuntu 24.04 -- gcc 9.3.0
Switch
Dell 2048 -- 10Gbps switch (10Gbps and 1Gbps interfaces)