# HG changeset patch # User Joerg Sonnenberger # Date 1591694551 -7200 # Node ID 02b17231f6c395dd96abe1969bd3f0184082cebc # Parent baffdfa5bd1a9ae39cfa695b608305b39f6cdce9 util: provide a helper function to estimate RAM size For POSIX systems, it uses sysconf. For Windows, it uses the win32 API directly. Differential Revision: https://phab.mercurial-scm.org/D8644 diff -r baffdfa5bd1a -r 02b17231f6c3 mercurial/configitems.py --- a/mercurial/configitems.py Thu Jul 02 19:59:59 2020 +0200 +++ b/mercurial/configitems.py Tue Jun 09 11:22:31 2020 +0200 @@ -1231,6 +1231,10 @@ b'ui', b'askusername', default=False, ) coreconfigitem( + b'ui', b'available-memory', default=None, +) + +coreconfigitem( b'ui', b'clonebundlefallback', default=False, ) coreconfigitem( diff -r baffdfa5bd1a -r 02b17231f6c3 mercurial/ui.py --- a/mercurial/ui.py Thu Jul 02 19:59:59 2020 +0200 +++ b/mercurial/ui.py Tue Jun 09 11:22:31 2020 +0200 @@ -2119,6 +2119,22 @@ if (b'ui', b'quiet') in overrides: self.fixconfig(section=b'ui') + def estimatememory(self): + """Provide an estimate for the available system memory in Bytes. + + This can be overriden via ui.available-memory. It returns None, if + no estimate can be computed. + """ + value = self.config(b'ui', b'available-memory') + if value is not None: + try: + return util.sizetoint(value) + except error.ParseError: + raise error.ConfigError( + _(b"ui.available-memory value is invalid ('%s')") % value + ) + return util._estimatememory() + class paths(dict): """Represents a collection of paths and their configs. diff -r baffdfa5bd1a -r 02b17231f6c3 mercurial/util.py --- a/mercurial/util.py Thu Jul 02 19:59:59 2020 +0200 +++ b/mercurial/util.py Tue Jun 09 11:22:31 2020 +0200 @@ -3626,3 +3626,44 @@ locale.setlocale(locale.LC_CTYPE, oldloc) else: yield + + +def _estimatememory(): + """Provide an estimate for the available system memory in Bytes. + + If no estimate can be provided on the platform, returns None. + """ + if pycompat.sysplatform.startswith(b'win'): + # On Windows, use the GlobalMemoryStatusEx kernel function directly. + from ctypes import c_long as DWORD, c_ulonglong as DWORDLONG + from ctypes.wintypes import Structure, byref, sizeof, windll + + class MEMORYSTATUSEX(Structure): + _fields_ = [ + ('dwLength', DWORD), + ('dwMemoryLoad', DWORD), + ('ullTotalPhys', DWORDLONG), + ('ullAvailPhys', DWORDLONG), + ('ullTotalPageFile', DWORDLONG), + ('ullAvailPageFile', DWORDLONG), + ('ullTotalVirtual', DWORDLONG), + ('ullAvailVirtual', DWORDLONG), + ('ullExtendedVirtual', DWORDLONG), + ] + + x = MEMORYSTATUSEX() + x.dwLength = sizeof(x) + windll.kernel32.GlobalMemoryStatusEx(byref(x)) + return x.ullAvailPhys + + # On newer Unix-like systems and Mac OSX, the sysconf interface + # can be used. _SC_PAGE_SIZE is part of POSIX; _SC_PHYS_PAGES + # seems to be implemented on most systems. + try: + pagesize = os.sysconf(os.sysconf_names['SC_PAGE_SIZE']) + pages = os.sysconf(os.sysconf_names['SC_PHYS_PAGES']) + return pagesize * pages + except OSError: # sysconf can fail + pass + except KeyError: # unknown parameter + pass