Skip to content
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

Correct macOS Used Memory. #1463

Closed
wants to merge 1 commit into from
Closed

Conversation

ghost
Copy link

@ghost ghost commented Dec 24, 2024

macOS memory usage statistics are wrong.

For correct values, consider doing what Apple does in their official top(1) utility: https://github.com/apple-opensource/top/blob/e7979606cf63270663a62cfe69f82d35cef9ba58/globalstats.c#L433-L435

After testing this pull request locally you will notice the values reported by top(1) for used memory will match what this pull request reports for that.

I personally believe what activity monitor reports for ram usage is less correct than top(1). As far as I know, top(1) is a part of the single unix specification, so it is more standardized in how it calculates these types of things, and in a way that will be cross-platform, (as top(1) is available out of the box on numerous unix-likes, and activity monitor is not).

The code currently in the main branch does not match top(1), nor activity monitor either, so this is a step in the right direction either way, regardless of whichever one you prefer to use to get these values.

macOS memory usage statistics are wrong.

For correct values, consider doing what Apple does in their official top(1) utility: https://github.com/apple-opensource/top/blob/e7979606cf63270663a62cfe69f82d35cef9ba58/globalstats.c#L433-L435

After testing this pull request locally you will notice the values reported by top(1) for used memory will match what the pull request reports for that.
@ghost
Copy link
Author

ghost commented Dec 24, 2024

I'm surprised how many different software are seeming to get this wrong. For reference, I also had to fix it for Godot and Redot, and in their case the code was even farther away from being correct than fastfetch:

I think I'm also going to see if htop devs will accept my code. The way htop gets ram usage is slightly different from top, however they do that intentionally, so I'm not sure if they will accept my code. We'll see...

@CarterLi
Copy link
Member

top(1) is a part of the single unix specification

Which specification? I didn't find that in the list of standard POSIX commands

so it is more standardized in how it calculates these types of things, and in a way that will be cross-platform

It's not standardized. There is no standard to calcuate used memory bytes. In fact, it's also hard to define what is used (and free) memory. An Apple employee said that free memory is generally a nonsense value.

Note: the free memory is not memory physically not used at all (which is the value of free_count). For example, kernel usually caches loaded files to improve performance of future use, whose memory should not be considered as used because the memory can be dropped at any time.

Linux provides the standard free memory size, called MemAvailable, which defines free memory as the amount of memory that is available for a new workload, without pushing the system into swap. I doubt the accuracy of the value. For modern system supports memory compression, as the memory usage grows, much more cold memory data can be compressed. However before compression, I don't think there is a way to know how much memory can be actually saved by compressing. Therefore, as the author of MemAvailable said, it's still an estimation.

As there is no standard to calcuate used memory, you can't say a calcuation method is wrong, as long as it make sense somehow. Even Apple programs top and activity monitor can't agree with each other. top is available on some *nix platforms doesn't mean it is right.

@CarterLi
Copy link
Member

CarterLi commented Dec 25, 2024

macOS does provide a value like MemAvailable, called memory pressure level. It's a percentage value of general available memory reported directly by kernel. You can get the value by sysctl kern.memorystatus_level or memory_pressure | grep percentage. However, the official document says that the value takes swap into account so we can't use it.

@ghost
Copy link
Author

ghost commented Dec 25, 2024

All this is very insightful and good to know. Thank you for sharing. I'll leave it up to you whether this pull request should be closed or not.

I sort of assumed it was a part of the unix specification because it is a program included in nearly all unix-likes. My mistake if it is not listed there.

Edit:

I wanted to mention, how most platforms detect free memory is very different from how macOS does it and their official API's for doing this do in fact match what top shows for free memory even though macOS does not. As a result of most people using the official API's for this on their systems, programs like Godot, Redot, and even fastfetch are reporting the same thing for free memory that top is showing for unused memory on all platforms except macOS, I know this from my own testing. So I would say it would be better if macOS were consistent with other platforms and matched what top shows for unused memory. I even tested recently what fastfetch does on more obscure platforms like Solaris/illumos and it shows the same thing top does. Same also goes for used memory, most platforms besides macOS all these software are matching what top is showing.

@ghost
Copy link
Author

ghost commented Dec 26, 2024

This pull request isn't ready yet it appears. For some reason, even though I am using seemingly the exact-same code in this pull request, as what I am in my own fetch-like program called "sysinfo", my program is showing what top is, (while being rounded up/down in top), but in fastfetch the value reported is way less than what is being shown in top. I'm not sure why that is. It seems fastfetch is somehow managing to tamper with the value I'm assigning to ram->bytesUsed. Very strange. See it yourself in these screenshots, one of this pull request applied locally to fastfetch, and one of my sysinfo program:

Screenshot 2024-12-26 at 6 56 54 AM Screenshot 2024-12-26 at 6 58 34 AM

Feel free to test both programs hands on yourself with the following...

This pull request on fastfetch:

git clone -b patch-1 https://github.com/time-killer-games/fastfetch $HOME/fastfetch && cd $HOME/fastfetch  && cmake . && make && ./fastfetch

My sysinfo test case program:

git clone https://github.com/time-killer-games/sysinfo $HOME/sysinfo && $HOME/sysinfo/build.sh

You can see my code appears no different on the surface: https://github.com/time-killer-games/sysinfo/blob/e9f124270649c492466d6452d822d4d501d67ef0/system.cpp#L961

I'm about to go on vacation for a week starting this morning, so I will come back to trying to fix this after the new year.

@CarterLi
Copy link
Member

Man, please dont keep advertising your project. Thanks.

@ghost
Copy link
Author

ghost commented Dec 26, 2024

Man, please dont keep advertising your project. Thanks.

I find it extremely weird you think I was doing that at all. It was the only thing I had at the ready to demonstrate what I was talking about without needing to start a new project from scratch (just like what happened last time I shared it). You really don't need to be so unkind. I'm trying to help you and you only seem to get offended by that every time.

Most people disregard bug reports or bug fix pull requests if there is no minimal test case or steps to reproduce. You demand the opposite of what most people do.

Edit: I'm honestly not trying to provoke you, but most people also appreciate pull requests and bug reports because it helps their software improve without it having to be done all by one person on their own. Contributions such as these are good things. This is the second time you responded to me in a way as if these things are somehow a bad thing. If you don't want people helping, then you should mark this repository with a description that says you aren't accepting feedback or pull requests.

@CarterLi
Copy link
Member

You claim the memory usage detection of fastfetch and other similar projects are wrong without understanding what you are really talking about.

However it's a technical discussion. It's ok.

What I don't like is: you keep asking me trying your project. That's what so called: advertisement.

@CarterLi
Copy link
Member

CarterLi commented Dec 26, 2024

BTW, I highly recommand that you shouldn't use GLX to detect GPUs by default, because OpenGL doesn't support multi-GPU platform.

image

While fastfetch prints

$ fastfetch -s gpu --gpu-driver-specific --gpu-temp -l none -c none

GPU 1: NVIDIA GeForce RTX 3070 Ti Laptop GPU (5888) @ 1.78 GHz - 37.0°C (31.88 MiB / 7.68 GiB, 0%) [Discrete]
GPU 2: Intel Iris Xe Graphics (96) @ 1.40 GHz [Integrated]

@CarterLi
Copy link
Member

CarterLi commented Dec 26, 2024

Just took a look at your implementation of memory usage detection.

You used MemTotal - MemFree on Linux for used memory size. That is the size of physically used memory. Not saying it was wrong because it's completely about how you define the concept of used memory.

However, you used wire_count + inactive_count + active_count + compressor_page_count on macOS which is somewhat estimated used memory. They don't match each other. Putting these two methods in one project is wrong.

@CarterLi
Copy link
Member

Just took a look at your implementation of memory usage detection.

You used MemTotal - MemFree on Linux for used memory size. That is the size of physically used memory. Not saying it was wrong because it's completely about how you define the concept of used memory.

However, you used wire_count + inactive_count + active_count + compressor_page_count on macOS which is somewhat estimated used memory. They don't match each other. Putting these two methods in one project is wrong.

This also proved that you didn't really understand what used memory is.

@ghost
Copy link
Author

ghost commented Dec 26, 2024

You claim the memory usage detection of fastfetch and other similar projects are wrong without understanding what you are really talking about.

However it's a technical discussion. It's ok.

What I don't like is: you keep asking me trying your project. That's what so called: advertisement.

Ok, then treat everyone the same and not just me in that, please do not listen when people ask you to try their code. I can guarantee that will help make sure their pull requests will make your project more stable and not less (sigh). In case you were wondering, that's not how software development works, ever. You think it is advertisement because you want to believe that, even though it isn't in touch with what is really going on, at all. I don't care what you say, actually testing code, aside from reading documentation, is the only sane thing to do unless you want to just assume code works for no reason.

One thing I do agree with is that I shouldn't rely on GLX for GPU info, if anything, it should be a fallback used only when necessary and I get that, just like fastfetch, sysinfo is an ongoing work in progress. Thank you for the suggestion. I'm on vacation now but I'll be more than happy to look at it when I get back / have time.

You made the assumption I don't know what used or free memory is, when to be honest, it really seems like you don't know the exact definition of it either just by looking at how you have it done in fastfetch for macOS. You basically took swift code from someone else who had no idea what they were doing and assumed it was correct and then translated it into C. I may be horribly wrong about that, but that is exactly how it looks on the surface.

I admit I don't know everything on these topics, but I do know this, Apple's solution for top is bound to be way more correct than some random third party swift developer you found online. I hope that would makes sense to you why I feel that way. Most of my code solutions for RAM and SWAP usage in particular (not counting other things) are taken from what official OS userlands provide, (and yes I know linux has no official userland because it is a kernel and not an OS) or at least produce equal values to them, it's a very big claim to say you know more than OS vendors. I know I don't know more than them, and they are more likely to be right than I am. I get I may have not done that with every OS my software supports.

This ticket is about macOS ram usage in fastfetch and how to do it correctly. It has nothing to do with how I get GPU info in my program or what I do to get RAM usage on other platforms, if you reported these things in the right places at all, like in a ticket or pull request on my repository, it would actually be on topic and therefore it would be a lot more helpful than bringing it up here with the intention to insinuate I have no idea what I'm doing as a programmer. I reported my suggestions in the right place and with intention to help and not to trash your work (however it really feels like you think I am doing that, I'm not sure). I hope you consider to either do the same, or simply just not bring it up if it's too much trouble to file bug reports to me in the right place. I'm on your side.

@CarterLi
Copy link
Member

CarterLi commented Dec 27, 2024

You made the assumption I don't know what used or free memory is, when to be honest, it really seems like you don't know the exact definition of it either just by looking at how you have it done in fastfetch for macOS. You basically took swift code from someone else who had no idea what they were doing and assumed it was correct and then translated it into C. I may be horribly wrong about that, but that is exactly how it looks on the surface.

Again, there is neither a standard definition of free memory is, nor does macOS report a standard value of free memory size like Linux does. There is technically no right or wrong. As long as it's explicable, any result makes sense.

Yeah, as what you did in your project, I just want the result of fastfetch matches other famous application. At the early days of fastfetch, a lot people were comparing fastfetch and neofetch, and always thought that fastfetch was wrong if fastfetch printed different results from neofetch. Most people don't bother to file an issue to ask if it's a bug but just drop fastfetch immediately. Therefore, I chose the implementation of Stats. Not only because it's famous but also it seems to match the result of neofetch well.

That's it. The implementation is negotiable. I may change it to use top's implementation if more people ask. But for now, I want to keep the current implementation.

@ghost
Copy link
Author

ghost commented Dec 29, 2024

That's fine! No worries. Thank you for being so understanding.

@ghost
Copy link
Author

ghost commented Dec 29, 2024

I don't know if this was the case, but this post:

This pull request isn't ready yet it appears. For some reason, even though I am using seemingly the exact-same code in this pull request, as what I am in my own fetch-like program called "sysinfo", my program is showing what top is, (while being rounded up/down in top), but in fastfetch the value reported is way less than what is being shown in top. I'm not sure why that is. It seems fastfetch is somehow managing to tamper with the value I'm assigning to ram->bytesUsed. Very strange. See it yourself in these screenshots, one of this pull request applied locally to fastfetch, and one of my sysinfo program:
Screenshot 2024-12-26 at 6 56 54 AM Screenshot 2024-12-26 at 6 58 34 AM

Feel free to test both programs hands on yourself with the following...

This pull request on fastfetch:

git clone -b patch-1 https://github.com/time-killer-games/fastfetch $HOME/fastfetch && cd $HOME/fastfetch  && cmake . && make && ./fastfetch

My sysinfo test case program:

git clone https://github.com/time-killer-games/sysinfo $HOME/sysinfo && $HOME/sysinfo/build.sh

You can see my code appears no different on the surface: https://github.com/time-killer-games/sysinfo/blob/e9f124270649c492466d6452d822d4d501d67ef0/system.cpp#L961

I'm about to go on vacation for a week starting this morning, so I will come back to trying to fix this after the new year.

If you didn't read the actual text (or skimmed) or only saw the images, and missed the context of why I shared those screenshots to begin with, it makes a lot more sense why you thought I was advertising.

You see, I was saying that I was puzzled, because I am using the same exact code in this pull request that I am using in my test program, but they are not producing the same results as each other, despite seeming to be using the exact same code.

I shared that because I was hoping you might know why that is, so you could help steer me in the right direction to help get fastfetch show the same values as my test program (as well as top).

I hope that makes more sense now. I apologize if you already read/knew these things. I'm just trying to make sense of why you had the impression you did.

Edit: I initially tried to copy the link to the post I quoted here, but it just seemed to link to the original post in this ticket, I really wanted to avoid quoting it to not produce duplicated content, but it didn't seem to let me link to it properly for some reason.

If you already knew these thing feel free to remove this comment.

@CarterLi CarterLi closed this Dec 30, 2024
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.

1 participant