Sticky How to change the system memory division

      How to change the system memory division

      How to change the system memory division ?

      The default setting for system memory division is 50:50. That means 50% of memory for object store and 50% of memory for programs.
      It is possible to change this by using NetDCU tool memcfg.exe or the following code:

      Source Code

      1. extern "C" BOOL GetSystemMemoryDivision (
      2. LPDWORD lpdwStorePages,
      3. LPDWORD lpdwRamPages,
      4. LPDWORD lpdwPageSize );
      5. extern "C" DWORD SetSystemMemoryDivision ( DWORD );
      6. #define ONE_KB 1024
      7. #define SYSMEM_CHANGED 0
      8. #define SYSMEM_MUSTREBOOT 1
      9. #define SYSMEM_REBOOTPENDING 2
      10. #define SYSMEM_FAILED 3
      11. DWORD StorePages, RamPages, PageSize, TotPages;
      12. DWORD dwMemDivision = 50;
      13. if( !GetSystemMemoryDivision(&StorePages, &RamPages, &PageSize) )
      14. return FALSE;
      15. TotPages = StorePages+RamPages;
      16. StorePages = TotPages * (100 - dwMemDivision) / 100;
      17. DWORD dwRet = SetSystemMemoryDivision ( StorePages );
      18. if( SYSMEM_FAILED == dwRet )
      19. {
      20. ERRORMSG(1,(_T("Can't enlarge prgram memory (%d)\r\n"), GetLastError()));
      21. return FALSE;
      22. }

      the code for, but without errorhandling:

      Public Class Form1
      <DllImport("coredll.dll")> Private Shared Function GetSystemMemoryDivision( _
      ByRef lpdwStorePages As Integer, _
      ByRef ldpwRamPages As Integer, _
      ByRef ldpwPageSize As Integer) As Integer
      End Function

      <DllImport("coredll.dll")> Private Shared Function SetSystemMemoryDivision( _
      ByVal dwStorePages As Integer) As Integer
      End Function

      Public Shared Sub SetMemory(ByVal division As Integer)
      Dim storePages, ramPages, pageSize, totalPages As Integer
      If GetSystemMemoryDivision(storePages, ramPages, pageSize) = 1 Then
      totalPages = storePages + ramPages
      storePages = CInt(totalPages * (100 - division) / 100)
      Call SetSystemMemoryDivision(storePages)
      End If
      End Sub

      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      'Set Memory 90%
      End Sub
      End Class

      best regard Benjamin

      change system memory division on PicoMOD1

      I tried to change the system memory division on a PicoMOD1 using the registry entry "MemDivision" as described in the above, but it does not work. After booting I expected to find a changed allocation rate (40:60 for instance if I set MemDivision to 60) but it is always 50:50 regardless of what MemDivision value is set.

      If I run memcfg manually from command line it works well, I can set the allocation as I want it.

      After that I find the registry key "HKLM\System\MEMCFG\" but no entry value "MemDivision" exists.

      1. What is the reason why I can not influence the system memory divsion by registry?

      2. What is the recommended minimum size for the "Storage Memory" size in kB which should be always allocated?

      a) you have to set "MemDivision" under "HKLM\System\MEMCFG\"
      b) you have to autostart "memcfg.exe" while booting (via key "HKLM\Init" or put it into the autostart folder)
      then it will be work.

      The recommended minimum size of "Storage Memory" is visible under ControlPanel->System->Memory. Note, all files attached into the RAM will be enlarge "Storage Memory" (e.g, ftp log file, ...)

      thank you for your anser. I have some more question:

      What are the dependencies of MEMCFG and where should I insert the entry in Launch list? (Should it be in Launch40 for instance?)

      How can I find out which files and objects are attached into the RAM area at runtime (to estimate the potential need of storage memory)?

      I know that all files of my application normally are placed in RAM respectively Storage Memory (if they are not in the folders \FFSDISK, \Hard Disk and \Storage Card).

      I found out that the memory allocation and the use between Storage and Application Memory are differing, use of storage Memory was about 5% and application memory was about 80% while running a simple CF2-Application. This is a quite difficult situation because there is no swap disk or anything like that as known from desktop computers. While testing the OS behaviour when going near 100% use of application memory the system tried to change allocation rate, stopp application programs and then went to hang up, even the clock in system tray stopped. Of course, this was a hard test and should lead to extrem condition by intention. It showed me to be aware of memory use, and to have some reserves.

      1) you should start it before "your" program is launched. Or even better -change the division by your own application (see code above).

      2) this is a really difficult question - it depends on the processes you run. I suggest if you neeed more then 85% program memory you shoud switch to a NetDCUx with 64MB/(128MB) RAM.

      Re: How to change the system memory division

      As there where a lot of question regarding this subject here are some additional notes.

      First of all, please note that the overall size of memory that can be used in general is a little lower than the amount of memory the board is equipped with. This is caused by the fact, that the WindowsCE kernel image always will remain in RAM completely. So if you have a board that features 32MB of RAM and you are running a kernel image with a size of about 12MB, there will be 20MB left. This amount will also be shown in the systems dialog.
      Note: The exact value might even be a little lower as there are some additional kernel and system resources that will consume memory (e.g. internal data structures and reserved buffers like the video framebuffer, MMU mapping table, ...). There are some other threads in this forum, disucssing this issue.

      Storage Memory and Program Memroy
      Based on the example above there are now 20MB of memory left. These memory now will be devided into "Storage Memory" and "Program Memroy".
      • Storage Memory is used by the Object Store (CEDB database,...) and it also includes all files that are stored in virtual RAM filesystem which is the root directly. Only \FFSDISK is mapped to persistant storage (NAND Flash).
      • Program Memory is reserved for usage by applications.

      Controlling the memory devision (Storage <-> Program)
      By default the division of Storage and Program Memory is set to a value that is predefined in the WindowsCE kernel. this value may be different for each F&S module or kernel. To control this division there are three possiblities:

      1) Change the predifined division value in kernel: This method is only usable in combination with a custom kernel image (addition costs). Please contact <!-- e --><a href=""></a><!-- e --> to get more information.

      2) Change the division in the system control panel: There is a control panel applet available that shows the current memory division and gives you the posibility to modify the current division.
      Attention: Unfortunatly changes to the memory division are not persistant. This means that the default memory division, builtin in the kernel, will always be restored when rebooting the device.

      3) Use the SetSystemMemoryDivision() function on WindowsCE startup: The SetSystemMemoryDivision() function is used to change the memory division dynamically. As the the division settings can not be stored permamently a custom division must be set programmatically on startup.
      The memcfg utility available for download above is a small sample program that can be used to arange this very easily. You may set the desired memory division in registry and add the memcfg utility into init-key in registry. A small subset of the source code is also available above, so that you may be able to add this functionatly within your own application.

      Memcfg Utility
      As noted above this programm mainly is used for demonstration purposes. In most cases you may use the SetSystemMemoryDivision() system function within your application.
      Memcfg will read a percent value from registry each time it is beeing called. This value is located at [HKLM\System\MEMCFG\MemDivision]. Here is a small ndcucfg script that will create the required key and value for you:

      Source Code

      1. reg open \System
      2. reg create key MEMCFG
      3. reg set value MemDivision dword 50
      4. reg save

      You can also use the program by calling "memcfg -M <n>" to create these values.

      To start the memcfg utility on startup you additionally need to create a new entry in init-key:

      Source Code

      1. reg open \init
      2. reg set val Launch101 string \FFSDISK\memcfg.exe
      3. set val Depend101 hex 1e,00
      4. reg save

      Note: Please make sure that memcfg utility is available in the corresponding location (\FFSDISK).

      After arranging this modifications, memcfg should set the division automtically on WindowsCE startup.

      • Maximum range and granularity: It may not be possible to set the division for program and storage memory to a maximum value of 0% resp. 100%. There always is a small amount of storage memory required by WindowsCE. Additionatly granularity always is based on pages (4KB).
        Unfortunaly the memcfg program may not set the maximum possible value automatically so that a MemDivision value of 100 may not effect the memory division accordingly. For that reason it may always be a good reason to call the SetSystemMemoryDivision() function within your application to get an exact controll of memory division.

      Related articles and links
      The Object Store
      MSDN blog message regarding system memory division
      Software developer, F&amp;S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.

      I tried the memcfg program on an Armstone A9 board. The program works but only reductions of the standard storage size are accepted, not increases.
      The board is configured with approx. 132 MB storage size and approx. 840 MB program memory (from which 190 MB is in use).

      After recompilation of the memcfg program, and adding some debug statements the SetSystemMemoryDivision() routine does not return any error (return code 0).

      Why can I not increase the storage size on the Armstone A9?

      which kernel version you are using?
      Can you not adjust storage size at all or is there a limit?

      Can you verify this misbehaviour using ControlPanle->Sytsem->Memory ... ?

      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.
      >>Any feedback on this issue?
      <<Insofar the we can confirm and add the issue to our roadmap for release V2.40.
      F&S Elektronik Systeme GmbH
      As this is an international forum, please try to post in English.
      Da dies ein internationales Forum ist, bitten wir darum, Beiträge möglichst in Englisch zu verfassen.