Shining Arcanine wrote:I once opened Task Manager to find Firefox using over 400MB of RAM. I do not blame it for all my memory issues, but its memory consumption is an issue.
Firefox definitely has issues with regard to eating memory -- I commonly find it sitting on 500MB+ committed. But you get it back when you kill it, so if you're finding memory permanently "missing" then something else is using it. It may be a startup app, a service, or a device driver. Your best bet is to run ProcessExplorer, sort by ProcessName, and look at the WorkingSet column. When you sort by ProcessName you get a sort of tree display that allows you to drill down into the Sytem process and Svchost instances to see what's getting loaded.
Flying Fox wrote:Did you confirm if the System Cache has not increased as you notice the "memory drop"? The OS manages the System Cache and will put more RAM for it if it thinks it can use the RAM, so your "physically available" RAM may not increase after apps are closed.
Well, System Cache is used for recently-accessed files, so it does grow as apps use data files. But the number reported for System Cache in TaskMan (but not in perfmon) also includes the Standby Page list, which is all the not-recently-used pages that get liberated when an app has its workingset trimmed. The workingset can get trimmed for a variety of reasons: the app requests it, the system is low on memory, etc, but most commonly it is because the app was minimized. The default WndProc implementation that most apps use automatically requests a trim of its workingset whenever the user minimizes the app. This is considered good behavior (Firefox, notably, goes out of its way to avoid this, in yet another example of it acting as a bad citizen). Those trimmed pages get placed in the Standy List, so they're available when all the other pages (in the Free and Zero lists) are exhausted, but unless they actually do get used by something else they're still available if the app needs them again (if, for example, the user immediately unminimizes the app). You can see this behavior in Taskman: minimize some large app (
not Firefox) and watch the values for both Available memory and the System Cache grow.
I did not say that the memory usage of shared libraries is hidden; I said that shared libraries that are not in use by any applications that are running are not counted as part of any application's memory usage. If a single library uses 5MB of RAM and is being used by three applications, each of those applications will have 5MB of RAM tacted onto their memory usage to reflect their use of that library. If those applications are closed and the library is not closed, then the library's memory usage is not shown as part of any application, as no application is using it. I never read about that second part; it followed logically from what I have read, namely at Channel9, where I read that due to how shared libraries work, the .NET framework's memory footprint is shown as a part of each application that uses it, which is why people consider it to be bloated. Unfortunately, I do not have the url to the thread at Channel9 where I read that, although I still consider it to be bloated.
Uh, this isn't really right. Libraries (that is, DLLs) can't "not be in use by any application." DLLs can't run by themselves; they have to be loaded into a process context so they can have a stack, heap, etc. This is why svchost.exe exists, to load and run services that are implemented as DLLs. Shared libraries might be in use by the OS itself rather than any application, but if they're in memory they are in use by something. If code in a library allocates memory on behalf of an app (for example you're running a .NET app and it uses something out of System.Collection) then that memory gets allocated out of the app's virtual address space and is accounted for in the app's working set of memory. Shared DLLs use the heap and the stack of whichever app happens to be calling them (Windows itself is just a bunch of DLLs and -- outside of the kernel -- works in exactly the same way). As each app quits, those memory pages get freed and returned to the available list. If the last app using a DLL quits, then the DLL itself (its code pages) gets freed, because it no longer has a process to "live in." It is possible for a DLL to allocate memory outside of any particular application through the use of mapped files; this is the accepted way to share memory between processes. However, that memory is freed when the DLL itself is unloaded, and as I said that happens when the last app that is using the DLL quits.
What can be a little confusing is that memory gets used for different things, and are accounted for in different ways, and to compound the confusion the same things can have different names in TaskMan, Perfmon, and ProcessExplorer (and, as we saw with System Cache above, the things with the same name can actually refer to different things, too). You have to distinguish between physical and virtual memory, of course, but also between code pages and data pages, and virtual memory that is backed by the page file and memory that isn't. When you load a set of large DLLs like the .NET libraries, you're pulling in a lot of code pages (though only the pages that are used, which in a well-designed DLL won't be close to the size of the DLL on disk). Those code pages are mapped into the address space of each app that loads the DLL, so they contribute to its reported workingset, but they aren't backed in the page file (they're read-only, so they can just be discarded and reloaded from the on-disk image if necessary). So in that sense the library "bloats" the application, but you're getting a lot of functionality in the process (I only consider it bloat if I can get the same functionality while using significantly less memory; considering the .NET libraries include a JIT native code compiler, a garbage collected memory manager, and a lot of other functionality, it may be more than I need in some cases but given the productivity it gives me I would have a hard time calling it bloat). In
some cases, the DLL code pages only exist in memory once, even when they're in use by multiple applications. This, however, led to what was known as "DLL Hell" (where applications that expected to use a newer version of a DLL instead found themselves using an older version that was brought into memory by another, already-running application). So, since Win2K, many DLLs are loaded "side-by-side": each app that uses them gets its own copy. This means each app uses more memory, because the same DLL image may be in memory multiple times, but reliability is increased and you no longer have to worry about DLL Hell: it's a trade-off. (Again, in this regard it's worth noting that Windows itself is essentially just a collection of DLLs, and there's only ever one copy of each of them). Of course, you could just use statically-linked libraries, in which case the libraries
always bloat your code (and in many other OSes that's your only option)
Now, of course, there's more to it than that, and I don't want to get into a complete exposition on memory management in Windows. So to get back to the original question: it's not unusual for an actively-used system to have its available memory decrease somewhat over time, because of caching, code and data pages getting pulled in as code paths are executed, etc. If that's all you're seeing, it's nothing to worry about. On the other hand, if you're seeing a slow but essentially continuous drop in available memory, then something may be leaking -- likely a long-lived executable such as a service, driver, etc -- and digging around with ProcessExplorer may help you track it down.