Skip to content

Commit

Permalink
Add sys.getsizeof by intertally using java-size.jar extlib (Apache2 l…
Browse files Browse the repository at this point in the history
…icense), and add gc.get_objects by returning the monitoredObjects list (not quite CPython behaviour but close) to support muppy #2450
  • Loading branch information
darjus committed Jan 4, 2016
1 parent f322296 commit a74bfd4
Show file tree
Hide file tree
Showing 6 changed files with 104 additions and 10 deletions.
2 changes: 1 addition & 1 deletion Lib/test/test_support.py
Expand Up @@ -1000,7 +1000,7 @@ def gc_collect():
gc.collect()


_header = '2P'
_header = '1P'
if hasattr(sys, "gettotalrefcount"):
_header = '2P' + _header
_vheader = _header + 'P'
Expand Down
76 changes: 75 additions & 1 deletion 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):

Expand Down Expand Up @@ -273,12 +275,84 @@ def test_ioencoding(self): # from v2.7 test
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()
2 changes: 2 additions & 0 deletions build.xml
Expand Up @@ -155,6 +155,7 @@ oracle.jar=C:/workspace/HEAD/for_development/bisdevsrv28/jboss/server/infra/lib/
<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"/>
Expand Down Expand Up @@ -604,6 +605,7 @@ The readme text for the next release will be like:
<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"/>
Expand Down
Binary file added extlibs/java-sizeof-0.0.5.jar
Binary file not shown.
11 changes: 10 additions & 1 deletion src/org/python/core/PySystemState.java
Expand Up @@ -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;
Expand Down Expand Up @@ -432,6 +432,15 @@ public int getrecursionlimit() {
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");
Expand Down
23 changes: 16 additions & 7 deletions 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;
Expand Down Expand Up @@ -2558,13 +2554,26 @@ public static PyObject get_threshold() {
}

/**
* 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);
}

/**
Expand Down

0 comments on commit a74bfd4

Please sign in to comment.