Formatting Virtual Memory Display
-
I am working on a program that displays Physical, Virtual, and Combined memory amounts both in Totals and Available results, and I wish to have the options to display in "KB", "MB", or "GB". Ok, this is simple enough and I have the physical memory displaying just fine. However I am having trouble displaying the Virtual Memory properly, I know that my machine has 3072 MB set but I am getting some very wild return figures using this code: mVirtualMemory = My.Computer.Info.TotalVirtualMemory to display in KB I use the following method that I use for Physical Memory: mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory However I am getting this: mVirtualMemory = 8589934464 I do not understand what I am doing wrong, please help!
DB_Cooper1950 "Life is like a box of..."
What did you define
mVirtualMemory
as? What's the return type on this function you created? The value returned by TotalVirtualMemory is an Unsigned Long (ULong), or a 64-bit unsigned integer. If the types you're using are smaller, like using 32-bit Integers, you can get some unexpected results.Public Function GetTotalVMSizeInKb() As ULong
Dim x As ULong = My.Computer.Info.TotalVirtualMemory
Return (x / 1024)
End FunctionDave Kreskowiak Microsoft MVP - Visual Basic
-
What did you define
mVirtualMemory
as? What's the return type on this function you created? The value returned by TotalVirtualMemory is an Unsigned Long (ULong), or a 64-bit unsigned integer. If the types you're using are smaller, like using 32-bit Integers, you can get some unexpected results.Public Function GetTotalVMSizeInKb() As ULong
Dim x As ULong = My.Computer.Info.TotalVirtualMemory
Return (x / 1024)
End FunctionDave Kreskowiak Microsoft MVP - Visual Basic
Dave, Thank you for your reply, below is the full Property that I used in the class. Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property
DB_Cooper1950 "Life is like a box of..."
-
Dave, Thank you for your reply, below is the full Property that I used in the class. Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property
DB_Cooper1950 "Life is like a box of..."
You didn't specify what mVirtualMemory was before you used it, so it defaulted to an Integer type. Change it to this and it should work:
Public ReadOnly Property VirtualMemory() As ULong
Get
Dim vVirtualMemory As ULong = My.Computer.Info.TotalVirtualMemory
Return (mVirtualMemory / 1024)
End Get
End PropertyOr, you can just avoid the entire variable declaration thing altogether and do this:
Public ReadOnly Property VirtualMemory() As ULong
Get
Return (My.Computer.Info.TotalVirtualMemory / 1024)
End Get
End PropertyDave Kreskowiak Microsoft MVP - Visual Basic
-
You didn't specify what mVirtualMemory was before you used it, so it defaulted to an Integer type. Change it to this and it should work:
Public ReadOnly Property VirtualMemory() As ULong
Get
Dim vVirtualMemory As ULong = My.Computer.Info.TotalVirtualMemory
Return (mVirtualMemory / 1024)
End Get
End PropertyOr, you can just avoid the entire variable declaration thing altogether and do this:
Public ReadOnly Property VirtualMemory() As ULong
Get
Return (My.Computer.Info.TotalVirtualMemory / 1024)
End Get
End PropertyDave Kreskowiak Microsoft MVP - Visual Basic
Dave Kreskowiak wrote:
You didn't specify what mVirtualMemory was before you used it, so it defaulted to an Integer type. Change it to this and it should work:
Dave, Actually I did declare the variable mVirtualMemory as shown below. I just did not include this in the last entry. ... Private mVirtualMemory As ULong ... After that is when I used it here...
Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property
mVirtualMemory as you see is declared as a private ULong variable in the class that I wrote. So do you see anywhere else that I made a mistake? Thank you. DB_Cooper1950 "Life is like a box of..." -
Dave Kreskowiak wrote:
You didn't specify what mVirtualMemory was before you used it, so it defaulted to an Integer type. Change it to this and it should work:
Dave, Actually I did declare the variable mVirtualMemory as shown below. I just did not include this in the last entry. ... Private mVirtualMemory As ULong ... After that is when I used it here...
Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property
mVirtualMemory as you see is declared as a private ULong variable in the class that I wrote. So do you see anywhere else that I made a mistake? Thank you. DB_Cooper1950 "Life is like a box of..."Nope. No other mistakes, save the only other one is your assuming you have a complete understanding of virtual memory under Windows. It's entirely possible to have this much "Virtual Memory", depending on your systems configuration. TotalVirtualMemory does NOT equal pagefile size! Oh! And using a "global" variable like this (mVirtualMemory) is really bad practice! You're violating rules of Encapsulation and making it harder to debug your code. There is no reason, that I can see, for having that variable declared in Class scope. It should have been done inside the Property code.
Dave Kreskowiak Microsoft MVP - Visual Basic
-
Nope. No other mistakes, save the only other one is your assuming you have a complete understanding of virtual memory under Windows. It's entirely possible to have this much "Virtual Memory", depending on your systems configuration. TotalVirtualMemory does NOT equal pagefile size! Oh! And using a "global" variable like this (mVirtualMemory) is really bad practice! You're violating rules of Encapsulation and making it harder to debug your code. There is no reason, that I can see, for having that variable declared in Class scope. It should have been done inside the Property code.
Dave Kreskowiak Microsoft MVP - Visual Basic
Dave Kreskowiak wrote:
Oh! And using a "global" variable like this (mVirtualMemory) is really bad practice! You're violating rules of Encapsulation and making it harder to debug your code. There is no reason, that I can see, for having that variable declared in Class scope. It should have been done inside the Property code.
Dave, Please take a look at the following and then let me know that it is "Bad Practice", when the variable is used elsewhere in the class... Public Class SystemMemory #Region "Variables..." Private mPhysicalMemory As Long Private mVirtualMemory As ULong Private mCombinedMemory As Long Private mAvailablePhysicalMemory As Long Private mAvailableVirtualMemory As ULong Private mAvailableCombinedMemory As Long Private mInstance As SystemMemory Private mPctPhysicalMemory As Integer Private mPctVirtualMemory As Integer Private mPctCombinedMemory As Integer #End Region #Region "Constructors and Destructors..." Public Sub New() mInstance = Me End Sub Protected Overrides Sub Finalize() mInstance = Nothing End Sub #End Region #Region "Main Body in KB's..." Public ReadOnly Property PhysicalMemory() As Long Get mPhysicalMemory = My.Computer.Info.TotalPhysicalMemory mPhysicalMemory =(mPhysicalMemory / 1024) Return mPhysicalMemory End Get End Property Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property Public ReadOnly Property CombinedMemory() As Long Get mCombinedMemory = (mPhysicalMemory + mVirtualMemory) Return mCombinedMemory End Get End Property .... I did not list where it is used elsewhere, but it is not just used inside the property call as the other private variables are also used elsewhere. Is is incorrect to call and use them in that manner?
DB_Cooper1950 "Life is like a box of..."
-
Dave Kreskowiak wrote:
Oh! And using a "global" variable like this (mVirtualMemory) is really bad practice! You're violating rules of Encapsulation and making it harder to debug your code. There is no reason, that I can see, for having that variable declared in Class scope. It should have been done inside the Property code.
Dave, Please take a look at the following and then let me know that it is "Bad Practice", when the variable is used elsewhere in the class... Public Class SystemMemory #Region "Variables..." Private mPhysicalMemory As Long Private mVirtualMemory As ULong Private mCombinedMemory As Long Private mAvailablePhysicalMemory As Long Private mAvailableVirtualMemory As ULong Private mAvailableCombinedMemory As Long Private mInstance As SystemMemory Private mPctPhysicalMemory As Integer Private mPctVirtualMemory As Integer Private mPctCombinedMemory As Integer #End Region #Region "Constructors and Destructors..." Public Sub New() mInstance = Me End Sub Protected Overrides Sub Finalize() mInstance = Nothing End Sub #End Region #Region "Main Body in KB's..." Public ReadOnly Property PhysicalMemory() As Long Get mPhysicalMemory = My.Computer.Info.TotalPhysicalMemory mPhysicalMemory =(mPhysicalMemory / 1024) Return mPhysicalMemory End Get End Property Public ReadOnly Property VirtualMemory() As ULong Get mVirtualMemory = My.Computer.Info.TotalVirtualMemory mVirtualMemory = mVirtualMemory / 1024 Return mVirtualMemory End Get End Property Public ReadOnly Property CombinedMemory() As Long Get mCombinedMemory = (mPhysicalMemory + mVirtualMemory) Return mCombinedMemory End Get End Property .... I did not list where it is used elsewhere, but it is not just used inside the property call as the other private variables are also used elsewhere. Is is incorrect to call and use them in that manner?
DB_Cooper1950 "Life is like a box of..."
It is! Watch what happens when I get rid of all the class-scoped variables:
Public Class SystemMemory
' Say "Bye-Bye" to all the class-scoped variables! From what I can see in your code,
' you don't need a single one of them.
' I have no idea what you're doing with this stuff, but if the rest of this
' class is like your properties, you can get rid of this entire Region.
#Region "Constructors and Destructors..."
Public Sub New()
mInstance = Me
End Sub
Protected Overrides Sub Finalize()
mInstance = Nothing
End Sub
#End Region
#Region "Main Body in KB's..."
Public ReadOnly Property PhysicalMemory() As Long
Get
Return My.Computer.Info.TotalPhysicalMemory / 1024
End Get
End Property
Public ReadOnly Property VirtualMemory() As ULong
Get
Retrun My.Computer.Info.TotalVirtualMemory / 1024
End Get
End Property
Public ReadOnly Property CombinedMemory() As Long
' You can call your classes properties from inside
' the same class
Get
Return PhysicalMemory + VirtualMemory
End Get
End PropertyDave Kreskowiak Microsoft MVP - Visual Basic
-
It is! Watch what happens when I get rid of all the class-scoped variables:
Public Class SystemMemory
' Say "Bye-Bye" to all the class-scoped variables! From what I can see in your code,
' you don't need a single one of them.
' I have no idea what you're doing with this stuff, but if the rest of this
' class is like your properties, you can get rid of this entire Region.
#Region "Constructors and Destructors..."
Public Sub New()
mInstance = Me
End Sub
Protected Overrides Sub Finalize()
mInstance = Nothing
End Sub
#End Region
#Region "Main Body in KB's..."
Public ReadOnly Property PhysicalMemory() As Long
Get
Return My.Computer.Info.TotalPhysicalMemory / 1024
End Get
End Property
Public ReadOnly Property VirtualMemory() As ULong
Get
Retrun My.Computer.Info.TotalVirtualMemory / 1024
End Get
End Property
Public ReadOnly Property CombinedMemory() As Long
' You can call your classes properties from inside
' the same class
Get
Return PhysicalMemory + VirtualMemory
End Get
End PropertyDave Kreskowiak Microsoft MVP - Visual Basic
You are absolutely correct, I could shave all of that "extra" stuff off, and have cleaner code with much less lines of code that could go wrong. But it hasn't changed the actual return value. And you are correct I am not fully versed in Virtual memory values, THAT is why I am asking for help. :-D Dave Baker
DB_Cooper1950 "Life is like a box of..."
-
You are absolutely correct, I could shave all of that "extra" stuff off, and have cleaner code with much less lines of code that could go wrong. But it hasn't changed the actual return value. And you are correct I am not fully versed in Virtual memory values, THAT is why I am asking for help. :-D Dave Baker
DB_Cooper1950 "Life is like a box of..."
OK. The memory functions under My.Computer.Info are actually calling a Win32 API function called GlobalMemoryStatusEx[^]. This function fills a structure called MEMORYSTATUSEX[^] that lists various measurements of the various types of memory managed by Windows, from the CURRENT PROCESSES point of view! This means that it measures memory based on your applications view of it, not the System Wide Windows view of memory! There is a HUGE difference... When you call TotalPhysicalMemory and AvailablePhysicalMemory, you get the amount of physical memory reported by Windows, admittedly system-wide. But, this is NOT nocessarily all the physical memory in the machine. Some of it can be reserved by hardware for other functions, like shared video RAM. Calls to TotalVirtualMemory and AvailableVirtualMemory return the status of YOUR processes virtual address space, which can be MORE than the amount of physical RAM available to Windows. You can typically have 2GB of memory available to each process, even though your machine only has say, 512MB of physical RAM. How?? That's where the pagefile comes in. (Warning!! This explaination is very simplified!!) The pagefile is NOT virtual memory, but is a file that is used to store pages of memory that are allocated by all processes running in the system, combined. Say your machine has 512MB of RAM. The default pagefile size is 1.5x that size, or 768MB. So, if nothing is changed, Windows can have up to about 1.2GB of memory allocated acrossed all processes running in the system. But, it can only have 512MB of code and data in memory at any one time. Anything that is not being used, or the oldest memory pages that are still dirty, is swapped out to the pagefile to make room for pages that are needed. WHen you launch your process, it gets a new virtual address space of 1.2GB. There are user-mode (for your application) and kernel-mode portions of that space. After all, you still need to be able to call into the Windows Kernel to do stuff, like open a file, and that Kernel code sits at
-
OK. The memory functions under My.Computer.Info are actually calling a Win32 API function called GlobalMemoryStatusEx[^]. This function fills a structure called MEMORYSTATUSEX[^] that lists various measurements of the various types of memory managed by Windows, from the CURRENT PROCESSES point of view! This means that it measures memory based on your applications view of it, not the System Wide Windows view of memory! There is a HUGE difference... When you call TotalPhysicalMemory and AvailablePhysicalMemory, you get the amount of physical memory reported by Windows, admittedly system-wide. But, this is NOT nocessarily all the physical memory in the machine. Some of it can be reserved by hardware for other functions, like shared video RAM. Calls to TotalVirtualMemory and AvailableVirtualMemory return the status of YOUR processes virtual address space, which can be MORE than the amount of physical RAM available to Windows. You can typically have 2GB of memory available to each process, even though your machine only has say, 512MB of physical RAM. How?? That's where the pagefile comes in. (Warning!! This explaination is very simplified!!) The pagefile is NOT virtual memory, but is a file that is used to store pages of memory that are allocated by all processes running in the system, combined. Say your machine has 512MB of RAM. The default pagefile size is 1.5x that size, or 768MB. So, if nothing is changed, Windows can have up to about 1.2GB of memory allocated acrossed all processes running in the system. But, it can only have 512MB of code and data in memory at any one time. Anything that is not being used, or the oldest memory pages that are still dirty, is swapped out to the pagefile to make room for pages that are needed. WHen you launch your process, it gets a new virtual address space of 1.2GB. There are user-mode (for your application) and kernel-mode portions of that space. After all, you still need to be able to call into the Windows Kernel to do stuff, like open a file, and that Kernel code sits at
Dave, Thank you VERY much for that explaination, it makes a lot more sense to me now as to why I am not getting the exact amount of virtual memory that I thought that I was looking for. I realize that the explaination you gave was a simplified, but the point that you were trying to convey, was easier to understand that way, and for that I am grateful. David Baker
DB_Cooper1950 "Life is like a box of..."