[pypy-commit] pypy default: L2 cache size detection for non-x86 architectures

stefanor noreply at buildbot.pypy.org
Sat May 18 22:32:35 CEST 2013


Author: Stefano Rivera <stefano at rivera.za.net>
Branch: 
Changeset: r64283:ed146ac82e63
Date: 2013-05-18 19:45 +0200
http://bitbucket.org/pypy/pypy/changeset/ed146ac82e63/

Log:	L2 cache size detection for non-x86 architectures

diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py
--- a/rpython/memory/gc/env.py
+++ b/rpython/memory/gc/env.py
@@ -1,9 +1,10 @@
 """
 Utilities to get environ variables and platform-specific memory-related values.
 """
-import os, sys
+import os, sys, platform
 from rpython.rlib.rarithmetic import r_uint
 from rpython.rlib.debug import debug_print, debug_start, debug_stop
+from rpython.rlib.rstring import assert_str0
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.lltypesystem.lloperation import llop
 
@@ -130,7 +131,22 @@
 
 # ---------- Linux2 ----------
 
-def get_L2cache_linux2(filename="/proc/cpuinfo"):
+def get_L2cache_linux2():
+    arch = platform.machine()
+    if arch.endswith('86') or arch == 'x86_64':
+        return get_L2cache_linux2_cpuinfo()
+    if arch in ('alpha', 'ppc', 'ppc64'):
+        return get_L2cache_linux2_cpuinfo(label='L2 cache')
+    if arch == 'ia64':
+        return get_L2cache_linux2_ia64()
+    if arch in ('parisc', 'parisc64'):
+        return get_L2cache_linux2_cpuinfo(label='D-cache')
+    if arch in ('sparc', 'sparc64'):
+        return get_L2cache_linux2_sparc()
+    return -1
+
+
+def get_L2cache_linux2_cpuinfo(filename="/proc/cpuinfo", label='cache size'):
     debug_start("gc-hardware")
     L2cache = sys.maxint
     try:
@@ -154,7 +170,7 @@
         if _detect_arm_cpu(data):
             return -1
         while True:
-            start = _findend(data, '\ncache size', linepos)
+            start = _findend(data, '\n' + label, linepos)
             if start < 0:
                 break    # done
             linepos = _findend(data, '\n', start)
@@ -194,6 +210,104 @@
             "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
         return -1
 
+def get_L2cache_linux2_sparc():
+    debug_start("gc-hardware")
+    cpu = 0
+    L2cache = sys.maxint
+    while True:
+        try:
+            fd = os.open('/sys/devices/system/cpu/cpu' + assert_str0(str(cpu))
+                         + '/l2_cache_size', os.O_RDONLY, 0644)
+            try:
+                number = int(os.read(fd, 4096))
+            finally:
+                os.close(fd)
+        except OSError:
+            break
+        if number < L2cache:
+            L2cache = number
+        cpu += 1
+
+    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 "
+            "/sys/devices/system/cpu/cpuX/l2_cache_size")
+        return -1
+
+def get_L2cache_linux2_ia64():
+    debug_start("gc-hardware")
+    cpu = 0
+    L2cache = sys.maxint
+    L3cache = sys.maxint
+    while True:
+        cpudir = '/sys/devices/system/cpu/cpu' + assert_str0(str(cpu))
+        index = 0
+        while True:
+            cachedir = cpudir + '/cache/index' + assert_str0(str(index))
+            try:
+                fd = os.open(cachedir + '/level', os.O_RDONLY, 0644)
+                try:
+                    level = int(os.read(fd, 4096)[:-1])
+                finally:
+                    os.close(fd)
+            except OSError:
+                break
+            if level not in (2, 3):
+                index += 1
+                continue
+            try:
+                fd = os.open(cachedir + '/size', os.O_RDONLY, 0644)
+                try:
+                    data = os.read(fd, 4096)
+                finally:
+                    os.close(fd)
+            except OSError:
+                break
+
+            end = 0
+            while '0' <= data[end] <= '9':
+                end += 1
+            if end == 0:
+                index += 1
+                continue
+            if data[end] not in ('K', 'k'):    # assume kilobytes for now
+                index += 1
+                continue
+
+            number = int(data[:end])
+            number *= 1024
+
+            if level == 2:
+                if number < L2cache:
+                    L2cache = number
+            if level == 3:
+                if number < L3cache:
+                    L3cache = number
+
+            index += 1
+
+        if index == 0:
+            break
+        cpu += 1
+
+    mangled = L2cache + L3cache
+    debug_print("L2cache =", mangled)
+    debug_stop("gc-hardware")
+    if mangled > 0:
+        return mangled
+    else:
+        # Print a top-level warning even in non-debug builds
+        llop.debug_print(lltype.Void,
+            "Warning: cannot find your CPU L2 & L3 cache size in "
+            "/sys/devices/system/cpu/cpuX/cache")
+        return -1
+
+
 def _findend(data, pattern, pos):
     pos = data.find(pattern, pos)
     if pos < 0:
diff --git a/rpython/memory/gc/test/test_env.py b/rpython/memory/gc/test/test_env.py
--- a/rpython/memory/gc/test/test_env.py
+++ b/rpython/memory/gc/test/test_env.py
@@ -159,18 +159,11 @@
 fpu     : yes
 etc.
 """)
-    result = env.get_L2cache_linux2(str(filepath))
+    result = env.get_L2cache_linux2_cpuinfo(str(filepath))
     assert result == 3072 * 1024
 
 def test_estimate_best_nursery_size_linux2_arm():
-    filepath = udir.join('estimate_best_nursery_size_linux2')
-    filepath.write("""\
-Processor       : ARMv6-compatible processor rev 7 (v6l)
-# this is not actually from cpuinfo, but here for the test
-cache size      : 3072 KB
-...
-""")
-    result = env.get_L2cache_linux2(str(filepath))
+    result = env.get_L2cache_linux2()
     assert result == -1
 
 def test__detect_arm():


More information about the pypy-commit mailing list