-
Notifications
You must be signed in to change notification settings - Fork 404
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
zero runtime memory allocation application #2040
Comments
@lucabart97 Yes, you are right. This is some technical debt from the past and is originating here: iceoryx_dust/include/iceoryx_dust/cxx/serialization.hpp In the end, all occurrences of @lucabart97 since you unraveled the issue, would you like to have the chance to fix it? We would guide you through the pull request process, and we would be happy to have a new iceoryx contributer 😄 |
@elfenpiff Thank you for your quick response. I'll try to fix the ""issue"" myself, and I'll make a pull request once I'm done. |
@lucabart97 Awesome! Please add |
@lucabart97 I think it won't be that easy to remove the last In your specific case this would not be necessary since there is a more elegant solution which also prevents jitter in the latency when the monitoring is turned on. See also #1374. I'm talking about #1361. There are some proposals but they are also quite intrusive. A stop gap solution would be a simple counter or a 64 bit millisecond timestamp in the shared memory which is set by the application and checked by RouDi. Getting rid of the ... and then there is also #1133 😅 Anyway, whatever you choose, looking forward to your contribution :) |
Thank you, @elBoberido for the explanation. I investigated the code more closely to solve my problem. When using the However, when enabling monitor mode, the dynamic memory will appear: The "issue" in the master version is in the iceoryx/iceoryx_posh/include/iceoryx_posh/internal/runtime/ipc_message.inl Lines 27 to 42 in 4fb0b5f
So, @elfenpiff @elBoberido if we want to solve this issue, the solution seems to substitute the |
aaah I remember those lines. To replace the I think it should be sufficient if this is implemented for all integer, bool, float, double and char types. When we have this, we could write |
@lucabart97 @elfenpiff the After all of this is done, there is still the issue with the jitter when monitoring is turned on and additionally all the other IPC messages from the runtime need to be ported away from Saying that I would propose to work from bottom up instead of top down. This has the benefit to have multiple small PRs which are usually easier to review. My proposal is as follows:
Btw. the faster solution would still be to replace the keep alive message with a simple counter/timestamp in the shared memory. But it is more complicated for someone who does not know the code base and unfortunately we are lacking documentation for this part of the code base. If you need this to be fixed soonish I think I could spend a day to fix it in about one or two weeks and you could take care of the |
I see, the changes to perform the fix are a lot. I believe the problem was only in The iceoryx string type does not have iterator support. I see some std functions that use iterators in the code (e.g., Is it safe to use a fixed-size string length inside the Iceoryx API? If someone needs to send more than the fixed-size dimension, what can they do? What do you think about reserving or preallocating the std::string container at initialization time? And using If a simple counter/timestamp is enough for you, I think it is a better solution instead of using a string. |
@lucabart97 right, the small object optimization. I forgot about that. I does not really solve the problem but hides it quite well. Since the runtime name is also added to the string it would not be sufficient to only replace the It is fine to use iterators. If some container do not have them it is just because a lack of time no because we do not like to use them. Adding iterators to the For the template <uint64_t N>
expected<void, IpcChannelError> send(const Buffer<N>& buf) const noexcept; Preallocating the I hope I did not completely scare you away. Like I said before, if this is something pressing for you I could take care of refactoring the heart beat within the next one to two weeks. Since the documentation for this part of the code base is quite sparse and it would be faster for me to fix it myself instead of guiding you through all the pitfalls. It would be great though if you have time to work on the proposals to completely get rid of |
@elBoberido, no it is not a pressing thing for me, I just solved using the master version with the monitor disabled. I want to contribute given that I like the project and I use Iceoryx on my projects. |
@lucabart97 nice to hear :) If your time is limited I would suggest not to start with the Going bottom up would not add technical dept during the refactoring, at least not as much. Having an The vector capacity does also not need to be predefined since template <uint64_t N>
expected<void, IpcChannelError> send(const iox::vector<uint8_t, N>& buf) const noexcept {
static_assert(N <= platform::IOX_UDS_SOCKET_MAX_MESSAGE_SIZE, "Size exceeds transmission limit!");
} Using a Thinking further about this, it might easily get out of hands. Maybe we need more useful intermediate steps. Eventually we want to serialize to binary instead of ASCII but this is out of scope for now. This means we could still use On the template <template <uint64_t> class C, uint64_t N>
expected<void, IpcChannelError> send(const C<N>& buf) const noexcept;
template <template <uint64_t> class C, uint64_t N>
expected<C<N>, IpcChannelError> receive(iox::units::Duration timeout) const noexcept;
// alternatively, although I don't like out-parameters, in this case it might make sense
template <template <uint64_t> class C, uint64_t N>
expected<void, IpcChannelError> receive(C<N>& buf, iox::units::Duration timeout) const noexcept; There would be a specialization for iox::string<100> sendData {"test"};
iox::posix::UnixDomainSocket socket;
socket.send(sendData);
auto rec = socket.receive<iox::string, 100>(200_ms);
// or with the alternative API
iox::string<100> receiveData;
socket.receive(receiveData, 200_ms); Independent of the changes required to remove What do you think? cc @elfenpiff |
@lucabart97 once #2056 is merged, the applications should not allocate memory at runtime anymore. Would be great if you have time for the stuff I mentioned above :) |
Hi @elBoberido |
@elBoberido |
@lucabart97 I think once the new API is available and the code is ported, the std::string API can be removed |
Hi @elBoberido Some comments on what I have done:
Before creating the PR, you could check what I did in this fork because maybe you don't like the new API to the string container or you have some suggestions with If all is fine, I must understand if you have a script to format/indent the code. |
@lucabart97 no worries. Take your time. This is supposed to make fun and not to completely exhaust you :) I'll have a look at it later but AFAIR the |
@elBoberido |
@lucabart97 the general direction looks good. There is the issue with the I also think that the API I proposed needs changes. I did not look at the current API when proposing the The proposal with And finally, the proposal of this API was also not good template <template <uint64_t> class C, uint64_t N>
expected<void, IpcChannelError> send(const C<N>& buf) const noexcept; Methods cannot be specialized so it cannot be used for the vector implementation and a simple template <uint64_t N>
expected<void, IpcChannelError> send(const iox::string<N>& buf) const noexcept; would be sufficient. I'm also a bit surprised the tests pass but I guess that's by a lucky accident in how the Btw, I love the strings you used for testing ... all glory to the hypnotoad :) |
The idea without the copy is good and unsafe_raw_access([](auto* data) {
// do stuff with data
});
It might make sense to also have a cc @FerdinandSpitzschnueffler what do you think? The string is your domain :). The API is unsafe but with the |
@elBoberido |
@lucabart97 sounds great |
@elBoberido Sorry for the late response. I like your idea of |
I wrote the new string method, now I'm creating the test. |
@lucabart97 it's here https://github.com/eclipse-iceoryx/iceoryx/blob/master/CONTRIBUTING.md#testing In case your IDE supports generating code snippets from Javascript you can use this code to generate the UUID function create_UUID() {
var dt = new Date().getTime();
var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
var r = (dt + Math.random()*16)%16 | 0;
dt = Math.floor(dt/16);
return (c=='x' ? r :(r&0x3|0x8)).toString(16);
});
return uuid;
} |
Introduce a function to directly access the string pointer. This function enables checking the string's size and capacity after each call, minimizing the risk of encountering invalid strings. Signed-off-by: Luca Bartoli <[email protected]>
Introduce a function to directly access the string pointer. This function enables checking the string's size and capacity after each call, minimizing the risk of encountering invalid strings. Signed-off-by: Luca Bartoli <[email protected]>
Introduce a function to directly access the string pointer. This function enables checking the string's size and capacity after each call, minimizing the risk of encountering invalid strings. Signed-off-by: Luca Bartoli <[email protected]>
Introduce a function to directly access the string pointer. This function enables checking the string's size and capacity after each call, minimizing the risk of encountering invalid strings. Signed-off-by: Luca Bartoli <[email protected]>
Here is my proposal based on your suggestions: send API:
receive API:
internal API:
I used void to wrap I have another important question, the What do you suggest to do? I can keep this workflow for |
@lucabart97 I'm currently on travel and will give you some feedback after the weekend :) |
@lucabart97 the public API looks good. For the internal API it might be possible to achieve something similar with templates but that is an implementation detail and can be decided later. It might be necessary to extend the Regarding the You also have to keep in mind that there are three classed which need this adjustments. The |
Ok, got it! |
@lucabart97 yes, divide and conquer makes such changes much more manageable :) |
Required information
Operating system:
Ubuntu 20.04.6 LTS
Compiler version:
g++ (Ubuntu 9.4.0-1ubuntu1~20.04.2) 9.4.0
Eclipse iceoryx version:
v2.0.3 (Blueberry)
Heaptrack version:
heaptrack 1.4.80
Description
I have an application in C++ that uses Iceoryx that needs to be zero runtime memory allocation.
Checking the memory usage using heaptrack, there seems to be a periodic task inside Iceoryx that allocates a string to send the node's status.
There is a way to mitigate it?
Heaptrack flame graph
The text was updated successfully, but these errors were encountered: