-
-
Notifications
You must be signed in to change notification settings - Fork 440
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
darwin: Fix memory metrics support for Apple Silicon (ARM64) #1439
base: main
Are you sure you want to change the base?
Conversation
darwin/DarwinMachine.h
Outdated
@@ -19,6 +19,9 @@ typedef struct DarwinMachine_ { | |||
|
|||
host_basic_info_data_t host_info; | |||
vm_statistics_data_t vm_stats; | |||
#if defined(__arm64__) | |||
vm_statistics64_data_t vm_stats64; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This structure does not seem to be exclusive to ARM64. Would it be used in Intel Macs, too? A reference to Apple documentation would be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. According to the documentation:
https://developer.apple.com/documentation/kernel/vm_statistics64_data_t
https://developer.apple.com/documentation/kernel/vm_statistics_data_t
vm_statistics64_data_t can be used after macOS 10.6+
vm_statistics_data_t can be used after macOS 10.0+
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@SuCicada I prefer keeping a fallback mechanism when vm_statistics64_data_t
is not available. There is no reason to remove 32-bit Mac support (htop documentation doesn't state a minimum required version of macOS).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Haven't looked at the details of the implementation yet, but would it be feasible to check for vm_statistics64_data_t
and vm_statistics_data_t
in configure
and use the 64 bit version everywhere when available? And if none of both is available, we either fall back entirely or bail out at compile time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE Since it is said that vm_statistics_data_t
is available in OS X 10.0 (the very first Mac OS X), these is no need to check this one in particular in configure
. Just checking for vm_statistics64_data_t
is enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I will restore support for vm state 32.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly: Use vm_statistics64_data_t
when available, otherwise fall back to vm_statistics_data_t
.
darwin/DarwinMachine.c
Outdated
@@ -75,6 +85,9 @@ void Machine_scan(Machine* super) { | |||
host->prev_load = host->curr_load; | |||
DarwinMachine_allocateCPULoadInfo(&host->curr_load); | |||
DarwinMachine_getVMStats(&host->vm_stats); | |||
#if defined(__arm64__) | |||
DarwinMachine_getVMStats64(&host->vm_stats64); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to duplicate the effort of retrieving both vm_stats
structures?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just to prevent affecting existing functionality, but I checked the code again and it didn't affect anywhere else.
Same as above. I fix that.
darwin/DarwinMachine.c
Outdated
@@ -67,6 +67,16 @@ static void DarwinMachine_getVMStats(vm_statistics_t p) { | |||
} | |||
} | |||
|
|||
#if defined(__arm64__) | |||
static void DarwinMachine_getVMStats64(vm_statistics64_t p) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider merging this function with DarwinMachine_getVMStats
above, so as to avoid duplicate code.
You can use "DarwinMachine* this
" as the input argument.
darwin/Platform.c
Outdated
@@ -290,6 +290,24 @@ double Platform_setCPUValues(Meter* mtr, unsigned int cpu) { | |||
return CLAMP(total, 0.0, 100.0); | |||
} | |||
|
|||
#if defined(__arm64__) | |||
void Platform_setMemoryValues(Meter *mtr) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Consider merging two Platform_setMemoryValues
functions together.
darwin/Platform.c
Outdated
double page_K = (double) vm_page_size / (double) 1024; | ||
|
||
mtr->total = dhost->host_info.max_mem / 1024; | ||
int used = vm->active_count + vm->inactive_count + |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is it intentional to use signed int
type here? Note that vm->active_count
and similar members are in "natural_t
" type, which is unsigned.
Two general notes:
Also note the remarks earlier re implementation for both 32 and 64 bit VM structures using conditional compilation. |
Thank you for your guidance, I have resubmitted.
|
LGTM. Any particular reason for checking an architecture setting (64 bit support of the architecture) over explicit testing for availability of a concrete type/structure in |
Oh, You are right. It is more explicit to test the availability of a concrete type/structure in |
Thank you for your guidance, I have resubmitted.
What do you think |
configure.ac
Outdated
|
||
AC_MSG_CHECKING([for vm_statistics64 supported]) | ||
AC_COMPILE_IFELSE([ | ||
AC_LANG_PROGRAM([[ | ||
#include <mach/mach_host.h> | ||
#include <mach/vm_statistics.h> | ||
]], [[ | ||
mach_msg_type_number_t info_size = HOST_VM_INFO64_COUNT; | ||
vm_statistics64_data_t vm_stat; | ||
host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &info_size); | ||
]] | ||
)], | ||
AC_DEFINE([HAVE_VM_STATISTICS64], 1, [The vm_statistics64 features is supported.]) | ||
AC_MSG_RESULT(yes), | ||
AC_MSG_RESULT(no)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use things like this (untested)?
AC_MSG_CHECKING([for vm_statistics64 supported]) | |
AC_COMPILE_IFELSE([ | |
AC_LANG_PROGRAM([[ | |
#include <mach/mach_host.h> | |
#include <mach/vm_statistics.h> | |
]], [[ | |
mach_msg_type_number_t info_size = HOST_VM_INFO64_COUNT; | |
vm_statistics64_data_t vm_stat; | |
host_statistics64(mach_host_self(), HOST_VM_INFO64, (host_info64_t)&vm_stat, &info_size); | |
]] | |
)], | |
AC_DEFINE([HAVE_VM_STATISTICS64], 1, [The vm_statistics64 features is supported.]) | |
AC_MSG_RESULT(yes), | |
AC_MSG_RESULT(no)) | |
AC_CHECK_FUNCS([host_statistics64], [], [], [[#include <mach/vm_statistics.h>]]) | |
AC_CHECK_DECLS([vm_statistics64_data_t], [], [], [[#include <mach/vm_statistics.h>]]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@BenBE You and I suggested the same thing at the same time...
By the way, AC_CHECK_DECLS is not for checking type declarations, use AC_CHECK_TYPES instead. See my other comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had a look at the AutoConf docs, but didn't see it there somehow …
configure.ac
Outdated
@@ -330,6 +330,21 @@ if test "$my_htop_platform" = darwin; then | |||
AC_CHECK_FUNCS([mach_timebase_info]) | |||
AC_CHECK_DECLS([IOMainPort], [], [], [[#include <IOKit/IOKitLib.h>]]) | |||
AC_CHECK_DECLS([IOMasterPort], [], [], [[#include <IOKit/IOKitLib.h>]]) | |||
|
|||
AC_MSG_CHECKING([for vm_statistics64 supported]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought you can use AC_CHECK_TYPES
macro to simplify the check.
Maybe this is sufficient:
AC_CHECK_TYPES([struct vm_statistics64], [], [], [[#include <mach/vm_statistics.h>]]
dnl This defines HAVE_STRUCT_VM_STATISTICS64
Makes sense, but this will produce 2 macros. If use
I am not sure if there is a better solution, or if we can ignore this very unlikely situation. |
AutoConf has the ability to nest those macros, i.e. only check the second if the first succeeded. Likewise for the second macro: Only define the feature flag once the second macro succeeded too. Untested: AC_CHECK_FUNCS([host_statistics64], [
AC_CHECK_TYPES([struct vm_statistics64], [
AC_DEFINE([HAVE_VM_STATISTICS64], 1, [The vm_statistics64 features is supported.])
], [], [[#include <mach/vm_statistics.h>]])
], [], [[#include <mach/vm_statistics.h>]]) Check for |
@BenBE There would be AC_CHECK_TYPES([struct vm_statistics64], [
AC_CHECK_FUNCS([host_statistics64])
], [], [[#include <mach/vm_statistics.h>]])
dnl Then use HAVE_HOST_STATISTICS64 in the C code |
I know. The |
Thank you for your patient guidance, I have resubmitted. (In fact, I had previously attempted this method but mistakenly believed it didn't work🫣. After your confirmation, I have re-verified and got the correct compile result.👍) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure about the changed memory calculation. There seems something off …
#ifdef HAVE_STRUCT_VM_STATISTICS64 | ||
natural_t used = vm->active_count + vm->inactive_count + | ||
vm->speculative_count + vm->wire_count + | ||
vm->compressor_page_count - vm->purgeable_count - vm->external_page_count; | ||
mtr->values[MEMORY_METER_USED] = (double)(used - vm->compressor_page_count) * page_K; | ||
#else | ||
mtr->values[MEMORY_METER_USED] = (double)(vm->active_count + vm->wire_count) * page_K; | ||
#endif |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reasons for this calculation to differ between those two places, besides missing fields from the old struct?
Also, vm->compressor_page_count
is substracted twice AFAICS.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As #631 and #955 said, the current memory calculation may have a bit problem.
I referenced the code of exelban/stats and GuillaumeGomez/sysinfo(used by ClementTsang/bottom
mentioned by #955 )
There are some differences in details, but it seems that the main thing missing is adding vm->compressor_page_count
It seems that many people have raised the same issue of memory parameter display.
So I just want macOS to display the correct memory parameters. But there may be something I haven't considered.
I would suggest doing what Apple officially does in their top(1) program, as I suggested in my recent issue: #1573 |
Fix memory metrics of Apple Silicon (ARM64)
Detailed description: #631
The calculation of memory refers to exelban/stats Modules/RAM/readers.swift