[pypy-svn] r79394 - in pypy/trunk/pypy/rpython/memory/gc: . test

arigo at codespeak.net arigo at codespeak.net
Tue Nov 23 15:29:14 CET 2010


Author: arigo
Date: Tue Nov 23 15:29:12 2010
New Revision: 79394

Added:
   pypy/trunk/pypy/rpython/memory/gc/env.py
   pypy/trunk/pypy/rpython/memory/gc/test/test_env.py
Modified:
   pypy/trunk/pypy/rpython/memory/gc/base.py
   pypy/trunk/pypy/rpython/memory/gc/generation.py
   pypy/trunk/pypy/rpython/memory/gc/markcompact.py
   pypy/trunk/pypy/rpython/memory/gc/minimark.py
Log:
* Move things like reading env vars and poking at system files
  to the new file env.py.  Test it.

* Add PYPY_GC_MAX_DELTA to minimark.py, with comments.
  These env vars should ideally have some tests too...



Modified: pypy/trunk/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/base.py	Tue Nov 23 15:29:12 2010
@@ -5,7 +5,6 @@
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.support import AddressDict
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rlib.rarithmetic import r_uint
 
 TYPEID_MAP = lltype.GcStruct('TYPEID_MAP', ('count', lltype.Signed),
                              ('size', lltype.Signed),
@@ -410,42 +409,6 @@
     GCClass = getattr(module, classname)
     return GCClass, GCClass.TRANSLATION_PARAMS
 
-def _read_float_and_factor_from_env(varname):
-    import os
-    value = os.environ.get(varname)
-    if value:
-        if len(value) > 1 and value[-1] in 'bB':
-            value = value[:-1]
-        realvalue = value[:-1]
-        if value[-1] in 'kK':
-            factor = 1024
-        elif value[-1] in 'mM':
-            factor = 1024*1024
-        elif value[-1] in 'gG':
-            factor = 1024*1024*1024
-        else:
-            factor = 1
-            realvalue = value
-        try:
-            return (float(realvalue), factor)
-        except ValueError:
-            pass
-    return (0.0, 0)
-
-def read_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    return int(value * factor)
-
-def read_uint_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    return r_uint(value * factor)
-
-def read_float_from_env(varname):
-    value, factor = _read_float_and_factor_from_env(varname)
-    if factor != 1:
-        return 0.0
-    return value
-
 def _convert_callback_formats(callback):
     callback = getattr(callback, 'im_func', callback)
     if callback not in _converted_callback_formats:

Added: pypy/trunk/pypy/rpython/memory/gc/env.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/rpython/memory/gc/env.py	Tue Nov 23 15:29:12 2010
@@ -0,0 +1,245 @@
+"""
+Utilities to get environ variables and platform-specific memory-related values.
+"""
+import os, sys
+from pypy.rlib.rarithmetic import r_uint
+from pypy.rlib.debug import debug_print, debug_start, debug_stop
+
+# ____________________________________________________________
+# Reading env vars.  Supports returning ints, uints or floats,
+# and in the first two cases accepts the suffixes B, KB, MB and GB
+# (lower case or upper case).
+
+def _read_float_and_factor_from_env(varname):
+    value = os.environ.get(varname)
+    if value:
+        if len(value) > 1 and value[-1] in 'bB':
+            value = value[:-1]
+        realvalue = value[:-1]
+        if value[-1] in 'kK':
+            factor = 1024
+        elif value[-1] in 'mM':
+            factor = 1024*1024
+        elif value[-1] in 'gG':
+            factor = 1024*1024*1024
+        else:
+            factor = 1
+            realvalue = value
+        try:
+            return (float(realvalue), factor)
+        except ValueError:
+            pass
+    return (0.0, 0)
+
+def read_from_env(varname):
+    value, factor = _read_float_and_factor_from_env(varname)
+    return int(value * factor)
+
+def read_uint_from_env(varname):
+    value, factor = _read_float_and_factor_from_env(varname)
+    return r_uint(value * factor)
+
+def read_float_from_env(varname):
+    value, factor = _read_float_and_factor_from_env(varname)
+    if factor != 1:
+        return 0.0
+    return value
+
+
+# ____________________________________________________________
+# Get the total amount of RAM installed in a system.
+# On 32-bit systems, it will try to return at most the addressable size.
+# Note that if unknown it will just return the addressable size, which
+# will be huge on 64-bit systems.
+
+if sys.maxint == 2147483647:    # 32-bit
+    if sys.platform == 'linux2':
+        addressable_size = float(2**32)     # 4GB
+    elif sys.platform == 'win32':
+        addressable_size = float(2**31)     # 2GB
+    else:
+        addressable_size = float(2**31 + 2**30)   # 3GB (compromise)
+else:
+    addressable_size = float(2**63)    # 64-bit
+
+
+def get_total_memory_linux2(filename):
+    debug_start("gc-hardware")
+    result = -1.0
+    try:
+        fd = os.open(filename, os.O_RDONLY, 0644)
+        try:
+            buf = os.read(fd, 4096)
+        finally:
+            os.close(fd)
+    except OSError:
+        pass
+    else:
+        if buf.startswith('MemTotal:'):
+            start = _skipspace(buf, len('MemTotal:'))
+            stop = start
+            while stop < len(buf) and buf[stop].isdigit():
+                stop += 1
+            if start < stop:
+                result = float(buf[start:stop]) * 1024.0   # assume kB
+    if result < 0.0:
+        debug_print("get_total_memory() failed")
+        result = addressable_size
+    else:
+        debug_print("memtotal =", result)
+    debug_stop("gc-hardware")
+    return result
+
+
+if sys.platform == 'linux2':
+    def get_total_memory():
+        return get_total_memory_linux2('/proc/meminfo')
+
+#elif sys.platform == 'darwin':
+#    ...
+
+else:
+    def get_total_memory():
+        return addressable_size       # XXX implement me for other platforms
+
+
+# ____________________________________________________________
+# Estimation of the nursery size, based on the L2 cache.
+
+def best_nursery_size_for_L2cache(L2cache):
+    # Heuristically, the best nursery size to choose is about half
+    # of the L2 cache.  XXX benchmark some more.
+    if L2cache > 0:
+        return L2cache // 2
+    else:
+        return -1
+
+def get_L2cache_linux2(filename):
+    debug_start("gc-hardware")
+    L2cache = sys.maxint
+    try:
+        fd = os.open(filename, os.O_RDONLY, 0644)
+        try:
+            data = []
+            while True:
+                buf = os.read(fd, 4096)
+                if not buf:
+                    break
+                data.append(buf)
+        finally:
+            os.close(fd)
+    except OSError:
+        pass
+    else:
+        data = ''.join(data)
+        linepos = 0
+        while True:
+            start = _findend(data, '\ncache size', linepos)
+            if start < 0:
+                break    # done
+            linepos = _findend(data, '\n', start)
+            if linepos < 0:
+                break    # no end-of-line??
+            # *** data[start:linepos] == "   : 2048 KB\n"
+            start = _skipspace(data, start)
+            if data[start] != ':':
+                continue
+            # *** data[start:linepos] == ": 2048 KB\n"
+            start = _skipspace(data, start + 1)
+            # *** data[start:linepos] == "2048 KB\n"
+            end = start
+            while '0' <= data[end] <= '9':
+                end += 1
+            # *** data[start:end] == "2048"
+            if start == end:
+                continue
+            number = int(data[start:end])
+            # *** data[end:linepos] == " KB\n"
+            end = _skipspace(data, end)
+            if data[end] not in ('K', 'k'):    # assume kilobytes for now
+                continue
+            number = number * 1024
+            # for now we look for the smallest of the L2 caches of the CPUs
+            if number < L2cache:
+                L2cache = number
+
+    debug_print("L2cache =", L2cache)
+    debug_stop("gc-hardware")
+
+    if L2cache < sys.maxint:
+        return L2cache
+    else:
+        # Print a top-level warning even in non-debug builds
+        llop.debug_print(lltype.Void,
+            "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
+        return -1
+
+def _findend(data, pattern, pos):
+    pos = data.find(pattern, pos)
+    if pos < 0:
+        return -1
+    return pos + len(pattern)
+
+def _skipspace(data, pos):
+    while data[pos] in (' ', '\t'):
+        pos += 1
+    return pos
+
+
+if sys.platform == 'linux2':
+    def estimate_best_nursery_size():
+        """Try to estimate the best nursery size at run-time, depending
+        on the machine we are running on.  Linux code."""
+        L2cache = get_L2cache_linux2('/proc/cpuinfo')
+        return best_nursery_size_for_L2cache(L2cache)
+
+elif sys.platform == 'darwin':
+    from pypy.rpython.lltypesystem import rffi
+
+    sysctlbyname = rffi.llexternal('sysctlbyname',
+                                   [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
+                                    rffi.VOIDP, rffi.SIZE_T],
+                                   rffi.INT,
+                                   sandboxsafe=True)
+
+    def estimate_best_nursery_size():
+        """Try to estimate the best nursery size at run-time, depending
+        on the machine we are running on.
+        """
+        debug_start("gc-hardware")
+        L2cache = 0
+        l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
+        try:
+            len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
+            try:
+                size = rffi.sizeof(rffi.LONGLONG)
+                l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
+                len_p[0] = rffi.cast(rffi.SIZE_T, size)
+                # XXX a hack for llhelper not being robust-enough
+                result = sysctlbyname("hw.l2cachesize",
+                                      rffi.cast(rffi.VOIDP, l2cache_p),
+                                      len_p,
+                                      lltype.nullptr(rffi.VOIDP.TO), 
+                                      rffi.cast(rffi.SIZE_T, 0))
+                if (rffi.cast(lltype.Signed, result) == 0 and
+                    rffi.cast(lltype.Signed, len_p[0]) == size):
+                    L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
+                    if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
+                        L2cache = 0    # overflow!
+            finally:
+                lltype.free(len_p, flavor='raw')
+        finally:
+            lltype.free(l2cache_p, flavor='raw')
+        debug_print("L2cache =", L2cache)
+        debug_stop("gc-hardware")
+        if L2cache > 0:
+            return L2cache
+        else:
+            # Print a top-level warning even in non-debug builds
+            llop.debug_print(lltype.Void,
+                "Warning: cannot find your CPU L2 cache size with sysctl()")
+            return -1
+
+else:
+    def estimate_best_nursery_size():
+        return -1     # XXX implement me for other platforms

Modified: pypy/trunk/pypy/rpython/memory/gc/generation.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/generation.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/generation.py	Tue Nov 23 15:29:12 2010
@@ -2,7 +2,7 @@
 from pypy.rpython.memory.gc.semispace import SemiSpaceGC
 from pypy.rpython.memory.gc.semispace import GCFLAG_EXTERNAL, GCFLAG_FORWARDED
 from pypy.rpython.memory.gc.semispace import GC_HASH_TAKEN_ADDR
-from pypy.rpython.memory.gc.base import read_from_env
+from pypy.rpython.memory.gc import env
 from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena
 from pypy.rlib.objectmodel import free_non_gc_object
@@ -93,7 +93,7 @@
         if self.auto_nursery_size:
             newsize = nursery_size_from_env()
             if newsize <= 0:
-                newsize = estimate_best_nursery_size()
+                newsize = env.estimate_best_nursery_size()
             if newsize > 0:
                 self.set_nursery_size(newsize)
 
@@ -633,139 +633,5 @@
 
 # ____________________________________________________________
 
-import os
-
 def nursery_size_from_env():
-    return read_from_env('PYPY_GENERATIONGC_NURSERY')
-
-def best_nursery_size_for_L2cache(L2cache):
-    # Heuristically, the best nursery size to choose is about half
-    # of the L2 cache.  XXX benchmark some more.
-    return L2cache // 2
-
-
-if sys.platform == 'linux2':
-    def estimate_best_nursery_size():
-        """Try to estimate the best nursery size at run-time, depending
-        on the machine we are running on.
-        """
-        debug_start("gc-L2cache")
-        L2cache = sys.maxint
-        try:
-            fd = os.open('/proc/cpuinfo', os.O_RDONLY, 0644)
-            try:
-                data = []
-                while True:
-                    buf = os.read(fd, 4096)
-                    if not buf:
-                        break
-                    data.append(buf)
-            finally:
-                os.close(fd)
-        except OSError:
-            pass
-        else:
-            data = ''.join(data)
-            linepos = 0
-            while True:
-                start = findend(data, '\ncache size', linepos)
-                if start < 0:
-                    break    # done
-                linepos = findend(data, '\n', start)
-                if linepos < 0:
-                    break    # no end-of-line??
-                # *** data[start:linepos] == "   : 2048 KB\n"
-                start = skipspace(data, start)
-                if data[start] != ':':
-                    continue
-                # *** data[start:linepos] == ": 2048 KB\n"
-                start = skipspace(data, start + 1)
-                # *** data[start:linepos] == "2048 KB\n"
-                end = start
-                while '0' <= data[end] <= '9':
-                    end += 1
-                # *** data[start:end] == "2048"
-                if start == end:
-                    continue
-                number = int(data[start:end])
-                # *** data[end:linepos] == " KB\n"
-                end = skipspace(data, end)
-                if data[end] not in ('K', 'k'):    # assume kilobytes for now
-                    continue
-                number = number * 1024
-                # for now we look for the smallest of the L2 caches of the CPUs
-                if number < L2cache:
-                    L2cache = number
-
-        debug_print("L2cache =", L2cache)
-        debug_stop("gc-L2cache")
-
-        if L2cache < sys.maxint:
-            return best_nursery_size_for_L2cache(L2cache)
-        else:
-            # Print a top-level warning even in non-debug builds
-            llop.debug_print(lltype.Void,
-                "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
-            return -1
-
-    def findend(data, pattern, pos):
-        pos = data.find(pattern, pos)
-        if pos < 0:
-            return -1
-        return pos + len(pattern)
-
-    def skipspace(data, pos):
-        while data[pos] in (' ', '\t'):
-            pos += 1
-        return pos
-
-elif sys.platform == 'darwin':
-    from pypy.rpython.lltypesystem import rffi
-
-    sysctlbyname = rffi.llexternal('sysctlbyname',
-                                   [rffi.CCHARP, rffi.VOIDP, rffi.SIZE_TP,
-                                    rffi.VOIDP, rffi.SIZE_T],
-                                   rffi.INT,
-                                   sandboxsafe=True)
-
-    def estimate_best_nursery_size():
-        """Try to estimate the best nursery size at run-time, depending
-        on the machine we are running on.
-        """
-        debug_start("gc-L2cache")
-        L2cache = 0
-        l2cache_p = lltype.malloc(rffi.LONGLONGP.TO, 1, flavor='raw')
-        try:
-            len_p = lltype.malloc(rffi.SIZE_TP.TO, 1, flavor='raw')
-            try:
-                size = rffi.sizeof(rffi.LONGLONG)
-                l2cache_p[0] = rffi.cast(rffi.LONGLONG, 0)
-                len_p[0] = rffi.cast(rffi.SIZE_T, size)
-                # XXX a hack for llhelper not being robust-enough
-                result = sysctlbyname("hw.l2cachesize",
-                                      rffi.cast(rffi.VOIDP, l2cache_p),
-                                      len_p,
-                                      lltype.nullptr(rffi.VOIDP.TO), 
-                                      rffi.cast(rffi.SIZE_T, 0))
-                if (rffi.cast(lltype.Signed, result) == 0 and
-                    rffi.cast(lltype.Signed, len_p[0]) == size):
-                    L2cache = rffi.cast(lltype.Signed, l2cache_p[0])
-                    if rffi.cast(rffi.LONGLONG, L2cache) != l2cache_p[0]:
-                        L2cache = 0    # overflow!
-            finally:
-                lltype.free(len_p, flavor='raw')
-        finally:
-            lltype.free(l2cache_p, flavor='raw')
-        debug_print("L2cache =", L2cache)
-        debug_stop("gc-L2cache")
-        if L2cache > 0:
-            return best_nursery_size_for_L2cache(L2cache)
-        else:
-            # Print a top-level warning even in non-debug builds
-            llop.debug_print(lltype.Void,
-                "Warning: cannot find your CPU L2 cache size with sysctl()")
-            return -1
-
-else:
-    def estimate_best_nursery_size():
-        return -1     # XXX implement me for other platforms
+    return env.read_from_env('PYPY_GENERATIONGC_NURSERY')

Modified: pypy/trunk/pypy/rpython/memory/gc/markcompact.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/markcompact.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/markcompact.py	Tue Nov 23 15:29:12 2010
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
-from pypy.rpython.memory.gc.base import MovingGCBase, read_from_env
+from pypy.rpython.memory.gc.base import MovingGCBase
+from pypy.rpython.memory.gc import env
 from pypy.rlib.debug import ll_assert, have_debug_prints
 from pypy.rlib.debug import debug_print, debug_start, debug_stop
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
@@ -110,10 +111,10 @@
         return next
 
     def setup(self):
-        envsize = read_from_env('PYPY_MARKCOMPACTGC_MAX')
+        envsize = env.read_from_env('PYPY_MARKCOMPACTGC_MAX')
         if envsize >= 4096:
             self.space_size = envsize & ~4095
-        mincollect = read_from_env('PYPY_MARKCOMPACTGC_MIN')
+        mincollect = env.read_from_env('PYPY_MARKCOMPACTGC_MIN')
         if mincollect >= 4096:
             self.min_next_collect_after = mincollect
 

Modified: pypy/trunk/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/minimark.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/minimark.py	Tue Nov 23 15:29:12 2010
@@ -12,7 +12,7 @@
                         collection.
 
  PYPY_GC_GROWTH         Major collection threshold's max growth rate.
-                        Default is '1.3'.  Useful to collect more often
+                        Default is '1.4'.  Useful to collect more often
                         than normally on sudden memory growth, e.g. when
                         there is a temporary peak in memory usage.
 
@@ -22,6 +22,12 @@
                         crash the program with a fatal error.  Try values
                         like '1.6GB'.
 
+ PYPY_GC_MAX_DELTA      The major collection threshold will never be set
+                        to more than PYPY_GC_MAX_DELTA the amount really
+                        used after a collection.  Defaults to 1/8th of the
+                        total RAM size (or at most 4GB on 32-bit systems).
+                        Try values like '200MB'.
+
  PYPY_GC_MIN            Don't collect while the memory size is below this
                         limit.  Useful to avoid spending all the time in
                         the GC in very small programs.  Defaults to 8
@@ -36,7 +42,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase, MovingGCBase
-from pypy.rpython.memory.gc import minimarkpage, base, generation
+from pypy.rpython.memory.gc import minimarkpage, base, env
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask, r_uint
 from pypy.rlib.rarithmetic import LONG_BIT_SHIFT
 from pypy.rlib.debug import ll_assert, debug_print, debug_start, debug_stop
@@ -154,7 +160,7 @@
         # grow at most by the following factor from one collection to the
         # next.  Used e.g. when there is a sudden, temporary peak in memory
         # usage; this avoids that the upper bound grows too fast.
-        "growth_rate_max": 1.3,
+        "growth_rate_max": 1.4,
 
         # The number of array indices that are mapped to a single bit in
         # write_barrier_from_array().  Must be a power of two.  The default
@@ -198,6 +204,7 @@
         self.min_heap_size = 0.0
         self.max_heap_size = 0.0
         self.max_heap_size_already_raised = False
+        self.max_delta = 0.0
         #
         self.card_page_indices = card_page_indices
         if self.card_page_indices > 0:
@@ -288,7 +295,7 @@
             # handling of the write barrier.
             self.debug_always_do_minor_collect = newsize == 1
             if newsize <= 0:
-                newsize = generation.estimate_best_nursery_size()
+                newsize = env.estimate_best_nursery_size()
                 if newsize <= 0:
                     newsize = defaultsize
             newsize = max(newsize, minsize)
@@ -312,6 +319,12 @@
             if max_heap_size > 0:
                 self.max_heap_size = float(max_heap_size)
             #
+            max_delta = base.read_uint_from_env('PYPY_GC_MAX_DELTA')
+            if max_delta > 0:
+                self.max_delta = float(max_delta)
+            else:
+                self.max_delta = 0.125 * env.get_total_memory()
+            #
             self.minor_collection()    # to empty the nursery
             llarena.arena_free(self.nursery)
             self.nursery_size = newsize
@@ -345,6 +358,9 @@
         # Set the next_major_collection_threshold.
         threshold_max = (self.next_major_collection_threshold *
                          self.growth_rate_max)
+        if self.max_delta > 0.0:
+            threshold_max = min(threshold_max,
+                         self.next_major_collection_threshold + self.max_delta)
         if threshold > threshold_max:
             threshold = threshold_max
         #

Added: pypy/trunk/pypy/rpython/memory/gc/test/test_env.py
==============================================================================
--- (empty file)
+++ pypy/trunk/pypy/rpython/memory/gc/test/test_env.py	Tue Nov 23 15:29:12 2010
@@ -0,0 +1,133 @@
+import os, py
+from pypy.rpython.memory.gc import env
+from pypy.rlib.rarithmetic import r_uint
+from pypy.tool.udir import udir
+
+
+class FakeEnviron:
+    def __init__(self, value):
+        self._value = value
+    def get(self, varname):
+        assert varname == 'FOOBAR'
+        return self._value
+
+def check_equal(x, y):
+    assert x == y
+    assert type(x) == type(y)
+
+
+def test_read_from_env():
+    saved = os.environ
+    try:
+        os.environ = FakeEnviron(None)
+        check_equal(env.read_from_env('FOOBAR'), 0)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(0))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+        os.environ = FakeEnviron('')
+        check_equal(env.read_from_env('FOOBAR'), 0)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(0))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+        os.environ = FakeEnviron('???')
+        check_equal(env.read_from_env('FOOBAR'), 0)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(0))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+        os.environ = FakeEnviron('1')
+        check_equal(env.read_from_env('FOOBAR'), 1)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(1))
+        check_equal(env.read_float_from_env('FOOBAR'), 1.0)
+        #
+        os.environ = FakeEnviron('12345678')
+        check_equal(env.read_from_env('FOOBAR'), 12345678)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(12345678))
+        check_equal(env.read_float_from_env('FOOBAR'), 12345678.0)
+        #
+        os.environ = FakeEnviron('1234B')
+        check_equal(env.read_from_env('FOOBAR'), 1234)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(1234))
+        check_equal(env.read_float_from_env('FOOBAR'), 1234.0)
+        #
+        os.environ = FakeEnviron('1.5')
+        check_equal(env.read_float_from_env('FOOBAR'), 1.5)
+        #
+        os.environ = FakeEnviron('1.5Kb')
+        check_equal(env.read_from_env('FOOBAR'), 1536)
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(1536))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+        os.environ = FakeEnviron('1.5mB')
+        check_equal(env.read_from_env('FOOBAR'), int(1.5*1024*1024))
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(1.5*1024*1024))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+        os.environ = FakeEnviron('1.5g')
+        check_equal(env.read_from_env('FOOBAR'), int(1.5*1024*1024*1024))
+        check_equal(env.read_uint_from_env('FOOBAR'), r_uint(1.5*1024*1024*1024))
+        check_equal(env.read_float_from_env('FOOBAR'), 0.0)
+        #
+    finally:
+        os.environ = saved
+
+def test_get_total_memory_linux2():
+    filepath = udir.join('get_total_memory_linux2')
+    filepath.write("""\
+MemTotal:        1976804 kB
+MemFree:           32200 kB
+Buffers:          144092 kB
+Cached:          1385196 kB
+SwapCached:         8408 kB
+Active:          1181436 kB
+etc.
+""")
+    result = env.get_total_memory_linux2(str(filepath))
+    assert result == 1976804 * 1024
+
+def test_estimate_best_nursery_size_linux2():
+    filepath = udir.join('estimate_best_nursery_size_linux2')
+    filepath.write("""\
+processor   : 0
+vendor_id   : GenuineIntel
+cpu family  : 6
+model       : 37
+model name  : Intel(R) Core(TM) i5 CPU       M 540  @ 2.53GHz
+stepping    : 5
+cpu MHz     : 1199.000
+cache size  : 3072 KB
+physical id : 0
+siblings    : 4
+core id     : 0
+cpu cores   : 2
+apicid      : 0
+initial apicid  : 0
+fpu     : yes
+fpu_exception   : yes
+cpuid level : 11
+wp      : yes
+flags       : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm pbe syscall nx rdtscp lm constant_tsc arch_perfmon pebs bts rep_good xtopology nonstop_tsc aperfmperf pni pclmulqdq dtes64 monitor ds_cpl vmx smx est tm2 ssse3 cx16 xtpr pdcm sse4_1 sse4_2 popcnt aes lahf_lm ida arat tpr_shadow vnmi flexpriority ept vpid
+bogomips    : 5054.78
+clflush size    : 64
+cache_alignment : 64
+address sizes   : 36 bits physical, 48 bits virtual
+power management:
+
+processor   : 1
+vendor_id   : GenuineIntel
+cpu family  : 6
+model       : 37
+model name  : Intel(R) Core(TM) i5 CPU       M 540  @ 2.53GHz
+stepping    : 5
+cpu MHz     : 2534.000
+cache size  : 3072 KB
+physical id : 0
+siblings    : 4
+core id     : 0
+cpu cores   : 2
+apicid      : 1
+initial apicid  : 1
+fpu     : yes
+etc.
+""")
+    result = env.get_L2cache_linux2(str(filepath))
+    assert result == 3072 * 1024



More information about the Pypy-commit mailing list