Skip to content

MINIFICPP-1504: Add Resource consumption data to heartbeats#1032

Closed
martinzink wants to merge 10 commits intoapache:mainfrom
martinzink:MINIFICPP-1504-PR
Closed

MINIFICPP-1504: Add Resource consumption data to heartbeats#1032
martinzink wants to merge 10 commits intoapache:mainfrom
martinzink:MINIFICPP-1504-PR

Conversation

@martinzink
Copy link
Member

@martinzink martinzink commented Mar 18, 2021

Manual testing:
In MemoryUsageTest and CPUUsageTest with cout_enabled, one can manually verify the resource consumption with some thirdparty tool.
I've tested and got appropriate results on

  • AMD Ryzen 1600 32 GB desktop Manjaro
  • AMD Ryzen 1600 32 GB desktop Windows 10
  • Intel i7-8850G 16 GB laptop Ubuntu 18.04
  • Intel m3-7Y30 4 GB laptop Manjaro
  • Intel 2 Duo 8 GB macOS

These test results are available on MINIFICPP-1504


Thank you for submitting a contribution to Apache NiFi - MiNiFi C++.

In order to streamline the review of the contribution we ask you
to ensure the following steps have been taken:

For all changes:

  • Is there a JIRA ticket associated with this PR? Is it referenced
    in the commit message?

  • Does your PR title start with MINIFICPP-XXXX where XXXX is the JIRA number you are trying to resolve? Pay particular attention to the hyphen "-" character.

  • Has your PR been rebased against the latest commit within the target branch (typically main)?

  • Is your initial contribution a single, squashed commit?

For code changes:

  • If adding new dependencies to the code, are these dependencies licensed in a way that is compatible for inclusion under ASF 2.0?
  • If applicable, have you updated the LICENSE file?
  • If applicable, have you updated the NOTICE file?

For documentation related changes:

  • Have you ensured that format looks appropriate for the output in which it is rendered?

Note:

Please ensure that once the PR is submitted, you check GitHub Actions CI results for build issues and submit an update to your PR as soon as possible.

int64_t value;
};

class DoubleValue : public Value {
Copy link
Member Author

Choose a reason for hiding this comment

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

This class is required to be able to parse and deparse doubles in the heartbeat

/// Returns memory usage in bytes, including shared memory
uint64_t getMemoryUsage();
/// Returns physical memory usage by the current process in bytes
uint64_t getCurrentProcessPhysicalMemoryUsage();
Copy link
Member Author

Choose a reason for hiding this comment

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

I also looked into getting information about virtual memory but its meaning is wildly inconsistent between platforms and usually doesn't really hold useful information.

std::string ip_;
std::string device_id_;
static utils::SystemCPUUsageTracker cpu_load_tracker_;
static std::mutex cpu_load_tracker_mutex_;
Copy link
Member Author

Choose a reason for hiding this comment

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

this is static because CPU Usage tracking needs some persistent data, because it compares CPU ticks between heartbeats, but the response nodes are instantiated and destroyed with each heartbeat.

@martinzink martinzink marked this pull request as ready for review March 18, 2021 17:24
utsname buf;
SerializedResponseNode serializePhysicalMemoryUsageInformation() {
SerializedResponseNode used_physical_memory;
used_physical_memory.name = "memoryUtilization";
Copy link
Member

Choose a reason for hiding this comment

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

utilization:

the amount of something available, produced, etc. compared with the total amount that exists or that could be produced

Either we should return a percentage value here or rename this to something like memoryUsage.

Copy link
Member Author

Choose a reason for hiding this comment

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

good catch thanks, I've changed it to memoryUsage in d28d399

Copy link
Contributor

@arpadboda arpadboda left a comment

Choose a reason for hiding this comment

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

Mostly looks good, added some comments

SerializedResponseNode queuesize;
queuesize.name = "size";
queuesize.value = repo.second->getRepoSize();
for (auto &repo : repositories_) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Does it modify anything on the original container?
I don't see such line, so I would go with const & here

Copy link
Member Author

Choose a reason for hiding this comment

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

done d2832cf

SerializedResponseNode componentsNode(false);
componentsNode.name = "components";

for (auto component : components) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I know it's old code, but as we touch it - copy seems to be needless here.

Copy link
Member Author

Choose a reason for hiding this comment

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

done d2832cf

return components_node;
}

SerializedResponseNode serializeAgentMemoryUsage() {
Copy link
Contributor

Choose a reason for hiding this comment

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

This func could be const

Copy link
Member Author

Choose a reason for hiding this comment

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

done d2832cf


double SystemCPUUsageTracker::getCPUUsageAndRestartCollection() {
queryCPUTimes();
if (isCurrentQuerySameAsPrevious() || isCurrentQuerySameAsPrevious()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Do I miss something, or is it A || A?

I think in one of the conditions you wanted if check if query is older than previous

Copy link
Member Author

Choose a reason for hiding this comment

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

Oops, you are right. Fixed it in d2832cf

Comment on lines 17 to 18
#ifndef LIBMINIFI_INCLUDE_UTILS_PROCESSCPUUSAGETRACKER_H_
#define LIBMINIFI_INCLUDE_UTILS_PROCESSCPUUSAGETRACKER_H_
Copy link
Contributor

Choose a reason for hiding this comment

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

We should use #pragma once for all new headers.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed it in 007a486

Comment on lines 20 to 27
#if defined(__linux__) || defined(__APPLE__)
#include <time.h>
#endif

#ifdef WIN32
#include <cstdint>
#include "windows.h"
#endif
Copy link
Contributor

Choose a reason for hiding this comment

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

Could be a bit shorter

#ifdef WIN32
#include <cstdint>
#include "windows.h"
#else
#include <time.h>
#endif

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed it in 007a486

virtual double getCPUUsageAndRestartCollection() = 0;
};

#if defined(__linux__) || defined(__APPLE__)
Copy link
Contributor

Choose a reason for hiding this comment

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

Just a personal thought, but if all the implementation details are different on windows and unix platforms, maybe we could have separate files for windows and unix implementations and include the appropriate header file in compilation time. What do you think? Same for the SystemCPUUsageTracker

Copy link
Contributor

Choose a reason for hiding this comment

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

I see that you've already discussed this, it's okay to have it in a followup.

Comment on lines 50 to 51
bool isCurrentQueryOlderThanPrevious();
bool isCurrentQuerySameAsPrevious();
Copy link
Contributor

Choose a reason for hiding this comment

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

The isCurrent* functions could be const. Same comment for SystemCPUUsageTracker class.

Copy link
Member Author

Choose a reason for hiding this comment

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

fixed it in 007a486

namespace internal {

template<class T, class U>
bool cast_if_in_range(T in, U& out) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a bit conflicted about this as usually casts follow the snake_case style, but our code should follow the camelCase for function names.

Copy link
Member Author

Choose a reason for hiding this comment

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

yeah, now I am conflicted too. I was under the impression that freefunctions should be snake_case (while member functions should be lowerCamelCase) but there is no documentation about this besides the mentioning the google style guide (which uses UpperCamelCase and sometimes snake_case)

I don't have a strong preference and I am comfortable with either snake_case or lowerCamelCase here. What is your preference?

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't have any strong preference here either, so you can keep it as it is.

}

ValueParser& parse(double& out) {
double result; // NOLINT
Copy link
Contributor

Choose a reason for hiding this comment

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

Could we just initialize this to 0 to satisfy the linter?

Copy link
Member Author

Choose a reason for hiding this comment

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

sure, fixed it in 007a486

return -1;
return pmc.WorkingSetSize;
#else
static_assert(false, "Unsupported platform");
Copy link
Member

Choose a reason for hiding this comment

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

I want to go back to using dummy values or non-fatal warnings on unsupported platforms, instead of intentionally making the compilation fail even if the agent would work otherwise.
Aside from having to deal with manual cmake calls, there's not much stopping users to compile minifi c++ on non-linux POSIX platforms today, even though it's not tested.

Copy link
Member Author

Choose a reason for hiding this comment

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

Thanks thats a valid point, changed it to only warn and give back -1 as result in #1065

@arpadboda arpadboda closed this in d4cda02 Apr 27, 2021
dam4rus pushed a commit to dam4rus/nifi-minifi-cpp that referenced this pull request May 18, 2021
Signed-off-by: Arpad Boda <aboda@apache.org>

This closes apache#1032
@martinzink martinzink deleted the MINIFICPP-1504-PR branch March 6, 2023 08:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants