ros2 / realtime_support Goto Github PK
View Code? Open in Web Editor NEWMinimal real-time testing utility for measuring jitter and latency.
Minimal real-time testing utility for measuring jitter and latency.
Required Info:
timespec_to_long
returns incorrect value in Raspbian OS.
timespec_to_long
in my code, this issue occured.Here is an example code with my suggestions.
For simplicity, timespec_to_long
is copied from utils.h.
#include <iostream>
#include <time.h>
// copied code from rttest/include/rttest/utils.h:76
#define NSEC_PER_SEC 1000000000
static inline uint64_t timespec_to_long(const struct timespec * t)
{
return t->tv_sec * NSEC_PER_SEC + t->tv_nsec;
}
// my suggestion 1: tv_sec, tv_nsec seems long int in linux, use long long int.
static inline long long int timespec_to_long2(const struct timespec * t)
{
return (long long int)t->tv_sec * NSEC_PER_SEC + (long long int)t->tv_nsec;
}
// my suggestion 2: specify int64_t explicitly (uint64_t may be OK)
static inline int64_t timespec_to_long3(const struct timespec * t)
{
return (int64_t)t->tv_sec * NSEC_PER_SEC + (int64_t)t->tv_nsec;
}
int main(int argc, char *argv[])
{
struct timespec t;
clock_gettime(CLOCK_MONOTONIC_RAW, &t);
// check tv_sec, tv_nsec size and value
std::cout << "sizeof(t.tv_sec): " << sizeof(t.tv_sec)
<< " value: " << t.tv_sec
<< std::endl;
std::cout << "sizeof(t.tv_nsec): " << sizeof(t.tv_nsec)
<< " value: " << t.tv_nsec
<< std::endl;
// print timespec_to_long return value
std::cout << "timespec_to_long(&t): " << timespec_to_long(&t) << std::endl;
std::cout << "timespec_to_long2(&t): " << timespec_to_long2(&t) << std::endl;;
std::cout << "timespec_to_long3(&t): " << timespec_to_long3(&t) << std::endl;;
}
g++ above_code.cpp
and ./a.out
.Result in Ubuntu 18.04 x86_64:
sizeof(t.tv_sec): 8 value: 11940218
sizeof(t.tv_nsec): 8 value: 372300334
timespec_to_long(&t): 11940218372300334
timespec_to_long2(&t): 11940218372300334
timespec_to_long3(&t): 11940218372300334
Result in Raspbian OS:
sizeof(t.tv_sec): 4 value: 246386 // size is 4 not 8 in Raspbian OS
sizeof(t.tv_nsec): 4 value: 585632521 // size is 4 not 8 in Raspbian OS
timespec_to_long(&t): 1491730185 // oops
timespec_to_long2(&t): 246386585632521
timespec_to_long3(&t): 246386585632521
Required Info:
Build and run tests (with Connext installed):
colcon build --packages-up-to tlsf_cpp
colcon test --packages-select tlsf_cpp
Builds and tests pass.
Builds, but one of the tests fails:
$ colcon test-result --verbose
build/tlsf_cpp/test_results/tlsf_cpp/test_tlsf__rmw_connext_cpp.gtest.xml: 3 tests, 0 errors, 1 failure, 0 skipped
- tlsf_cpp.AllocatorTest__rmw_connext_cpp allocator_shared_ptr
<<< failure message
/root/ros2_ws/src/ros2/realtime_support/tlsf_cpp/test/test_tlsf.cpp:370
Value of: fail
Actual: true
Expected: false
>>>
ivanpauno/fix_issue_#668
(4b23cf464dca6feb42f84c0a8cfb1afb74ac1231)colcon build --symlink-install --packages-up-to rclcpp test_tlsf
colcon test --packages-select test_tlsf
The allocator_unique_ptr
test fail for the three vendors.
It's only failing in connext and passing in fastrtps and opensplice, when it shouldn't.
This stack trace:
/home/ivanpauno/ros2_ws/build/tlsf_cpp/test_tlsf__rmw_opensplice_cpp : operator new(unsigned long)+0x3b
Is marked as match
in check_stacktrace.
only because it contains opensplice in the test name. The same happens with fastrtps. It's not happening with connext, as is not part of the token list.
Such as do we need multi-threading in realtime etc.
Another executable with this name already exists in rclcpp_examples
: https://github.com/ros2/examples/blob/5978e9db5e7ea69f6b767434797ea52b48123f6e/rclcpp_examples/CMakeLists.txt#L42
(Rookie alert - I could just miss the obvious since I am a beginner with Linux)
I followed the installation instruction README.md and build rttest from source with:
mkdir build
cd build
cmake ..
sudo make instal
I then wanted to build the example by
cd examples
mkdir build
cd build
cmake .. (-DCMAKE_INSTALL_PREFIX=<build folder>)
make
./example_loop
However, example_loop.c has an #include <rttest/rttest.h>
, which did fail in my case unless I changed it to only #include <rttest.h>
.
The global install of rttest was targetting -- Installing: /usr/local/include/rttest.h
.
I did not figure out a working local installation with -DCMAKE_INSTALL_PREFIX=<build folder>
without changing example_loop.c .
Required Info:
git clone https://github.com/ros2/realtime_support.git
cd realtime_support
cd rttest
mkdir build
cd build
cmake ..
sudo make install
cd ..
cd examples
mkdir build
cd build
cmake ..
Scanning dependencies of target example_loop
[ 50%] Building C object CMakeFiles/example_loop.dir/example_loop.c.o
[100%] Linking C executable example_loop
[100%] Built target example_loop
Scanning dependencies of target example_loop
[ 50%] Building C object CMakeFiles/example_loop.dir/example_loop.c.o
/home/nicolasgerig/realtime_support/rttest/examples/example_loop.c:17:27: fatal error: rttest/rttest.h: No such file or directory
compilation terminated.
CMakeFiles/example_loop.dir/build.make:62: recipe for target 'CMakeFiles/example_loop.dir/example_loop.c.o' failed
make[2]: *** [CMakeFiles/example_loop.dir/example_loop.c.o] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/example_loop.dir/all' failed
make[1]: *** [CMakeFiles/example_loop.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
Update README or correct the example_loop.c?
Now I'm testing #94, I find this issue.
Required Info:
# ./example_loop -d 1gb -s rr -i 10000 -f out.txt
Writing results to file: out.txt
Initial major pagefaults: 0
Initial minor pagefaults: 262500
rttest statistics for new.txt:
- Minor pagefaults: 0
- Major pagefaults: 0
Latency (time after deadline was missed):
- Min: 9792 ns
- Max: 570881 ns
- Mean: 82055.158300 ns
- Standard deviation: 141.661569
If you run many times, you'll get large standard deviation such as 42949672.959047.
Anyway, run following to calcurate true standard deviation.
Different values are returned.
# run in ipython session
import numpy as np
np.loadtxt("out.txt", skiprows=1)[:, 2].std()
# 10,000 order value is returned, for example 27376.849010133381
see above
see above
To calcurate standard deviation, Rttest::calculate_statistics does following (I wrote python-numpy like formula after "i.e.".)
x = x - x.mean()
where x is jitter vector.x = np.dot(x, x)
x = math.sqrt(x/N)
To reduce the possibility of overflow, I propose to divide by sqrt(N) first.
x = x - x.mean()
x = x / sqrt(N)
x = np.dot(x, x)
x = math.sqrt(x)
Here is my workaround code(I get almost same output as numpy).
If OK, I'll send PR.
// Rttest::calculate_statistics in rttest.cpp
// https://github.com/ros2/realtime_support/blob/master/rttest/src/rttest.cpp#L839
// before
std::vector<int64_t> latency_diff(latency_dataset.size());
std::transform(
latency_dataset.begin(), latency_dataset.end(), latency_diff.begin(),
std::bind(std::minus<int>(), std::placeholders::_1, output->mean_latency));
int64_t sq_sum = std::inner_product(
latency_diff.begin(), latency_diff.end(), latency_diff.begin(), 0);
output->latency_stddev = std::sqrt(sq_sum / latency_dataset.size());
// after
std::transform(
latency_dataset.begin(), latency_dataset.end(), latency_diff.begin(),
std::bind(std::minus<int>(), std::placeholders::_1, output->mean_latency));
// forst divide by sqrt(n)
auto n = latency_dataset.size();
std::vector<double> latency_div(n);
std::transform(
latency_diff.begin(), latency_diff.end(), latency_div.begin(),
[n](int64_t x) -> double { return x / std::sqrt(n); });
// inner_product
int64_t sq_sum = std::inner_product(
latency_div.begin(), latency_div.end(), latency_div.begin(), 0);
output->latency_stddev = std::sqrt(sq_sum);
RT tutorial for ROS2 mentions that pendulum demo requires 8GB of ram, but does not reasons why. After playing around with rttest i finally was able to understand why it allocates 8GB (see answer), but it's still not clear where this prefault logic comes from and it seems 8GB are just accidentally there.
Is it possible to make memory requirement configurable or document/reason approach used in lock_and_prefault_dynamic
?
Thanks
Required Info:
./example_loop -i 10000
In other console open e.g. top
to check that RES memory is ~8GB.
I want to avoid hard requirement of 8+GB of RAM, so i expect this can be configurable for example.
As alternative documentation can justify 8GB memory requirement.
App requires 8GB RAM, which many boards don't have.
Using g++ 5.3 on Xenial the compiler warns about the following:
.../src/ros2/realtime_support/tlsf_cpp/test/test_tlsf.cpp:243:6: warning: ‘void operator delete(void*, size_t)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation) [-Wc++14-compat]
void operator delete(void * ptr, size_t) noexcept
^
.../src/ros2/realtime_support/tlsf_cpp/test/test_tlsf.cpp:243:6: warning: ‘void operator delete(void*, size_t)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation) [-Wc++14-compat]
void operator delete(void * ptr, size_t) noexcept
^
.../src/ros2/realtime_support/tlsf_cpp/test/test_tlsf.cpp:243:6: warning: ‘void operator delete(void*, size_t)’ is a usual (non-placement) deallocation function in C++14 (or with -fsized-deallocation) [-Wc++14-compat]
void operator delete(void * ptr, size_t) noexcept
^
The package.xml states GNU Lesser Public License 2.1
whereas, the source files (https://github.com/ros2/realtime_support/blob/master/tlsf_cpp/include/tlsf_cpp/tlsf.hpp#L3) state Apache License, Version 2.0
On Ubuntu Trusty installed using alpha1 binaries, the rtt_plot script has mode 0644.
Required Info:
See release build on Linux: https://ci.ros2.org/view/nightly/job/nightly_linux_release/1683/gcc/
No warnings
We see the warning:
char* __builtin_strncpy(char*, const char*, long unsigned int)’ output truncated before terminating nul copying as many bytes from a string as its length [-Wstringop-truncation] 106 | return __builtin___strncpy_chk (__dest, __src, __len, __bos (__dest));
The test was disabled in #84 and it needed to be disabled because the refactored intra-process manager in rclcpp unfortunately did not have the ability to control allocations in its merged state, see:
However, the plan is update that implementation soon to again take an allocator and allow for complete control over all allocations. At that time, the disabled test should be re-enabled.
Also, at the same time it would be a good idea to refactor this test to use https://github.com/osrf/osrf_testing_tools_cpp#memory_tools instead of a custom new
and delete
as that approach has limitations. Also to consider how it may not work correctly for all rmw implementations, see:
Build warnings under clang11.
I'm rather surprised that there isn't a deprecation warning in CI.
--- stderr: rttest
/opt/ros/master/src/ros2/realtime_support/rttest/src/rttest.cpp:843:10: warning: 'bind2nd<std::__1::minus<int>, double>' is deprecated [-Wdeprecated-declarations]
std::bind2nd(std::minus<int>(), output->mean_latency));
^
/usr/lib/llvm-11/bin/../include/c++/v1/functional:1089:1: note: 'bind2nd<std::__1::minus<int>, double>' has been explicitly marked deprecated here
_LIBCPP_DEPRECATED_IN_CXX11 inline _LIBCPP_INLINE_VISIBILITY
^
/usr/lib/llvm-11/bin/../include/c++/v1/__config:985:39: note: expanded from macro '_LIBCPP_DEPRECATED_IN_CXX11'
# define _LIBCPP_DEPRECATED_IN_CXX11 _LIBCPP_DEPRECATED
^
/usr/lib/llvm-11/bin/../include/c++/v1/__config:974:48: note: expanded from macro '_LIBCPP_DEPRECATED'
# define _LIBCPP_DEPRECATED __attribute__ ((deprecated))
^
1 warning generated.
---
Finished <<< rttest [23.7s]
I would like to give my user the capability to clear the current statistics, however rttest does not expose an API to clear the sample buffer. My reason for giving the user this capability is so they can remove the first iteration which has a much higher jitter than the other iterations due to it allocating memory at that time. My proposed solution is to expose a method in rttest that the client can call to clear the current sample buffer and reset the current results.
The solution sadly isn't as straightforward as clearing the sample buffer properties since there are a few methods that try to access elements using the current iteration. There is also no way to just reset the iteration back to zero since it is defined locally here:
for (size_t i = 0; i < iterations; i++) {
if (spin_once(user_function, args, & start_time, update_period, i) != 0) {
throw std::runtime_error("error in spin_once");
}
}
SInce there is no way to reset the iteration, my solution was to add a property to Rttest that stores the iteration that the sample buffer was cleared at. This way when the statistics are calculated, it could use this property as an offset causing it to ignore all statistics before this iteration. I defined a private property in Rttest as so:
size_t cleared_iteration = 0;
The implementation logic is pretty straightforward. FIrst, it sets the cleared_iteration property with the current results iteration. It then resets some of the results properties, such as the max and min latency. The method is shown below:
void Rttest::clear_statistics()
{
size_t i = this->results.iteration;
this->cleared_iteration = i;
// Reset the properties of the current results
this->results.max_latency = this->sample_buffer.latency_samples[i];
this->results.min_latency = this->results.max_latency;
this->results.mean_latency = this->results.max_latency;
this->results.minor_pagefaults = this->sample_buffer.minor_pagefaults[i];
this->results.major_pagefaults = this->sample_buffer.major_pagefaults[i];
}
The API method that the user can call:
int rttest_clear_statistics()
{
auto thread_rttest_instance = get_rttest_thread_instance(pthread_self());
if (!thread_rttest_instance) {
return -1;
}
thread_rttest_instance->clear_statistics();
return 0;
}
The only method that needs to be modified is calculate_statistics(...). Since calculate_stddev(...) requires a vector to be passed in, I had to create a sliced copy of the latency_samples. The alternative solution to creating a copy would be to create another calculate_stddev(...) method that takes in the beginning and end iterators instead of a vector. The code for the modified calculate_statistics(...) is shown below:
int Rttest::calculate_statistics(struct rttest_results * output)
{
if (output == NULL) {
fprintf(stderr, "Need to allocate rttest_results struct\n");
return -1;
}
std::vector<int64_t> latency_samples(this->sample_buffer.latency_samples.begin() + this->cleared_iteration + 1, this->sample_buffer.latency_samples.end());
output->min_latency = *std::min_element(latency_samples.begin(), latency_samples.end());
output->max_latency = *std::max_element(latency_samples.begin(), latency_samples.end());
output->mean_latency = std::accumulate(
latency_samples.begin(),
latency_samples.end(), 0.0) / latency_samples.size();
// Calculate standard deviation and try to avoid overflow
output->latency_stddev = calculate_stddev(latency_samples);
output->minor_pagefaults = std::accumulate(
this->sample_buffer.minor_pagefaults.begin()+this->cleared_iteration+1,
this->sample_buffer.minor_pagefaults.end(), 0);
output->major_pagefaults = std::accumulate(
this->sample_buffer.major_pagefaults.begin()+this->cleared_iteration+1,
this->sample_buffer.major_pagefaults.end(), 0);
return 0;
}
After some testing this implementation is working good for me. It would be very inconvenient to require my user to install a different version of rttest with my patch just to enable them to clear the statistics which is why I'm asking for this feature to be added. Even if my proposed solution isn't accepted, I would like to see this feature added as I'm sure this would be useful for other users as well.
While having different rmw suffixes all executables are using the default rmw impl.
i, i try to use https://github.com/ros2/rttest , but when i want to build the examples, it returns errors when running make:
rttest/build/include/rttest/rttest.h:29:21: error: expected ‘:’, ‘,’, ‘;’, ‘}’ or ‘attribute’ before ‘=’ token
size_t iterations = 0,
^
and some other lines with the same style of error ? in rttest.h is a struct, with the first entry with the line of above error ?
including stddef.h or changing size_t to unsigned int, doesnt change anything from the style of error ?
thanks for help flo
The Rttest
class stores pointers to custom allocated memory but does neither implement a correct copy constructor nor assignment operator (https://github.com/ros2/realtime_support/blob/master/rttest/src/rttest.cpp#L41-L57). These results in random segfaults.
Also affected is this variable:
Convert this repository to a hub for for other real-time repositories. Ideally, it would house documentation and a repos file
tlsf_cpp and rttest would be spun out as their own repositories, possibly hosted in the https://github.com/ros-realtime group.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.