[Jython-checkins] jython: Add sys.getsizeof by intertally using java-size.jar extlib (Apache2 license),

darjus.loktevic jython-checkins at python.org
Sun Jan 3 20:47:56 EST 2016


https://hg.python.org/jython/rev/c01bab7025e4
changeset:   7846:c01bab7025e4
user:        Darjus Loktevic <darjus at gmail.com>
date:        Mon Jan 04 12:47:40 2016 +1100
summary:
  Add sys.getsizeof by intertally using java-size.jar extlib (Apache2 license), and add gc.get_objects by returning the monitoredObjects list (not quite CPython behaviour but close) to support muppy #2450

files:
  Lib/test/test_support.py               |    2 +-
  Lib/test/test_sys.py                   |   76 ++++++++++++-
  build.xml                              |    2 +
  extlibs/java-sizeof-0.0.5.jar          |  Bin 
  src/org/python/core/PySystemState.java |   11 +-
  src/org/python/modules/gc.java         |   23 ++-
  6 files changed, 104 insertions(+), 10 deletions(-)


diff --git a/Lib/test/test_support.py b/Lib/test/test_support.py
--- a/Lib/test/test_support.py
+++ b/Lib/test/test_support.py
@@ -1000,7 +1000,7 @@
     gc.collect()
 
 
-_header = '2P'
+_header = '1P'
 if hasattr(sys, "gettotalrefcount"):
     _header = '2P' + _header
 _vheader = _header + 'P'
diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py
--- a/Lib/test/test_sys.py
+++ b/Lib/test/test_sys.py
@@ -1,6 +1,8 @@
 # -*- coding: iso-8859-1 -*-
 import unittest, test.test_support
 import sys, cStringIO
+import struct
+
 
 class SysModuleTest(unittest.TestCase):
 
@@ -273,12 +275,84 @@
         self.assertEqual(out, '?')
 
 
+class SizeofTest(unittest.TestCase):
+    """Jython modified version of getsizeof"""
+
+    def setUp(self):
+        self.P = struct.calcsize('P')
+        self.longdigit = sys.long_info.sizeof_digit
+        self.file = open(test.test_support.TESTFN, 'wb')
+
+    def tearDown(self):
+        self.file.close()
+        test.test_support.unlink(test.test_support.TESTFN)
+
+    check_sizeof = test.test_support.check_sizeof
+
+    def test_default(self):
+        size = test.test_support.calcobjsize
+        self.assertEqual(sys.getsizeof(True, -1), size('l'))
+
+    def test_objecttypes(self):
+        # check all types defined in Objects/
+        size = test.test_support.calcobjsize
+        vsize = test.test_support.calcvobjsize
+        check = self.check_sizeof
+        # bool
+        check(True, size('l'))
+        # buffer
+        with test.test_support.check_py3k_warnings():
+            check(buffer(''), size('1P2Pil'))
+        # builtin_function_or_method
+        check(len, size('3P'))
+        # bytearray_iterator
+        check(iter(bytearray()), size('2PP'))
+        # cell
+        def get_cell():
+            x = 42
+            def inner():
+                return x
+            return inner
+        check(get_cell().func_closure[0], size('2P'))
+        # classobj (old-style class)
+        class class_oldstyle():
+            def method():
+                pass
+        check(class_oldstyle, size('6P'))
+        # instance (old-style class)
+        check(class_oldstyle(), size('3P'))
+        # instancemethod (old-style class)
+        check(class_oldstyle().method, size('3P'))
+        # complex
+        check(complex(0,1), size('2P2d'))
+        # code
+        check(get_cell().func_code, size('4i3Pi3P'))
+        # BaseException
+        check(BaseException(), size('3P'))
+
+    def test_pythontypes(self):
+        # check all types defined in Python/
+        size = test.test_support.calcobjsize
+        vsize = test.test_support.calcvobjsize
+        check = self.check_sizeof
+        # imp.NullImporter
+        import imp
+        check(imp.NullImporter(self.file.name), size('3P'))
+        try:
+            raise TypeError
+        except TypeError:
+            tb = sys.exc_info()[2]
+            # traceback
+            if tb != None:
+                check(tb, size('2P2i'))
+
+
 def test_main():
     if test.test_support.is_jython:
         del SysModuleTest.test_lost_displayhook
         del SysModuleTest.test_refcount
         del SysModuleTest.test_setcheckinterval
-    test.test_support.run_unittest(SysModuleTest)
+    test.test_support.run_unittest(SysModuleTest, SizeofTest)
 
 if __name__ == "__main__":
     test_main()
diff --git a/build.xml b/build.xml
--- a/build.xml
+++ b/build.xml
@@ -155,6 +155,7 @@
             <pathelement path="${extlibs.dir}/guava-19.0.jar" />
             <pathelement path="${extlibs.dir}/icu4j-56.1.jar" />
             <pathelement path="${extlibs.dir}/jffi-1.2.10.jar"/>
+            <pathelement path="${extlibs.dir}/java-sizeof-0.0.5.jar"/>
             <pathelement path="${extlibs.dir}/jnr-ffi-2.0.7.jar"/>
             <pathelement path="${extlibs.dir}/jnr-netdb-1.1.5.jar"/>
             <pathelement path="${extlibs.dir}/jnr-posix-3.0.23.jar"/>
@@ -604,6 +605,7 @@
             <zipfileset src="extlibs/jffi-x86_64-Windows.jar"/>
 	    <!-- remainder of JNR, JFFI -->
             <zipfileset src="extlibs/jffi-1.2.10.jar"/>
+            <zipfileset src="${extlibs.dir}/java-sizeof-0.0.5.jar"/>
             <zipfileset src="${extlibs.dir}/jnr-ffi-2.0.7.jar"/>
             <zipfileset src="${extlibs.dir}/jnr-netdb-1.1.5.jar"/>
             <zipfileset src="${extlibs.dir}/jnr-posix-3.0.23.jar"/>
diff --git a/extlibs/java-sizeof-0.0.5.jar b/extlibs/java-sizeof-0.0.5.jar
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..23c555cc17af37962ea51431caf3755b1e85fb20
GIT binary patch
[stripped]
diff --git a/src/org/python/core/PySystemState.java b/src/org/python/core/PySystemState.java
--- a/src/org/python/core/PySystemState.java
+++ b/src/org/python/core/PySystemState.java
@@ -31,8 +31,8 @@
 import java.util.concurrent.locks.ReentrantLock;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
-
 import jnr.posix.util.Platform;
+import com.carrotsearch.sizeof.RamUsageEstimator;
 
 import org.python.Version;
 import org.python.core.adapter.ClassicPyObjectAdapter;
@@ -432,6 +432,15 @@
         return recursionlimit;
     }
 
+    @SuppressWarnings("unused")
+    public long getsizeof(Object obj, long defaultVal) {
+        return getsizeof(obj);
+    }
+
+    public long getsizeof(Object obj) {
+        return RamUsageEstimator.shallowSizeOf(obj);
+    }
+
     public void setrecursionlimit(int recursionlimit) {
         if (recursionlimit <= 0) {
             throw Py.ValueError("Recursion limit must be positive");
diff --git a/src/org/python/modules/gc.java b/src/org/python/modules/gc.java
--- a/src/org/python/modules/gc.java
+++ b/src/org/python/modules/gc.java
@@ -1,10 +1,6 @@
 package org.python.modules;
 
-import java.util.Set;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.IdentityHashMap;
-import java.util.HashSet;
+import java.util.*;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
@@ -2558,13 +2554,26 @@
     }
 
     /**
-     * Not supported by Jython.
+     * Only works reliably if {@code monitorGlobal} is active, as it depends on
+     * monitored objects to search for referrers. It only finds referrers that
+     * properly implement the traverseproc mechanism (unless reflection-based
+     * traversion is activated and works stable).
      * Throws {@link org.python.core.Py#NotImplementedError}.
      *
      * @throws org.python.core.Py.NotImplementedError
      */
     public static PyObject get_objects() {
-        throw Py.NotImplementedError("not applicable to Java GC");
+        if (!isMonitoring()) {
+            throw Py.NotImplementedError(
+                    "not applicable in Jython if gc module is not monitoring PyObjects");
+        }
+        LinkedList<PyObject> resultList = new LinkedList<>();
+        synchronized (monitoredObjects) {
+            for (WeakReferenceGC src: monitoredObjects) {
+                resultList.add((PyObject) src.get());
+            }
+        }
+        return new PyList(resultList);
     }
 
     /**

-- 
Repository URL: https://hg.python.org/jython


More information about the Jython-checkins mailing list