Rev 4681: Add a get_key() function, which then returns tuples for the given items. in http://bazaar.launchpad.net/~jameinel/bzr/2.1-memory-consumption
John Arbash Meinel
john at arbash-meinel.com
Tue Sep 8 22:06:21 BST 2009
At http://bazaar.launchpad.net/~jameinel/bzr/2.1-memory-consumption
------------------------------------------------------------
revno: 4681
revision-id: john at arbash-meinel.com-20090908210608-4fs0t0s43smepnzo
parent: john at arbash-meinel.com-20090908204304-bvrvpt10o8ux0e6z
committer: John Arbash Meinel <john at arbash-meinel.com>
branch nick: 2.1-memory-consumption
timestamp: Tue 2009-09-08 16:06:08 -0500
message:
Add a get_key() function, which then returns tuples for the given items.
-------------- next part --------------
=== modified file 'bzrlib/_keys_type_c.c'
--- a/bzrlib/_keys_type_c.c 2009-09-08 20:43:04 +0000
+++ b/bzrlib/_keys_type_c.c 2009-09-08 21:06:08 +0000
@@ -32,12 +32,29 @@
PyObject_HEAD
unsigned char key_width;
unsigned char num_keys; /* Not a Py_ssize_t like most containers */
- PyStringObject *key_strings[1];
+ PyStringObject *key_strings[1]; /* key_width * num_keys entries */
} Keys;
/* Forward declaration */
extern PyTypeObject KeysType;
+static void
+Keys_dealloc(Keys *keys)
+{
+ /* Do we want to use the Py_TRASHCAN_SAFE_BEGIN/END operations? */
+ if (keys->num_keys > 0) {
+ /* tuple deallocs from the end to the beginning. Not sure why, but
+ * we'll do the same here.
+ */
+ int i;
+ for(i = keys->num_keys - 1; i >= 0; --i) {
+ Py_XDECREF(keys->key_strings[i]);
+ }
+ }
+ Py_TYPE(keys)->tp_free((PyObject *)keys);
+}
+
+
static PyObject *
Keys_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
@@ -104,7 +121,7 @@
return NULL;
}
Py_INCREF(obj);
- self->key_strings[i] = obj;
+ self->key_strings[i] = (PyStringObject *)obj;
}
return (PyObject *)self;
}
@@ -112,7 +129,42 @@
static char Keys_doc[] =
"C implementation of a Keys structure";
+static PyObject *
+Keys_get_key(Keys *self, PyObject *args) {
+ long offset;
+ long start;
+ long i;
+ PyObject *tpl = NULL, *obj = NULL;
+
+ if (!PyArg_ParseTuple(args, "l", &offset)) {
+ return NULL;
+ }
+ if (offset >= self->num_keys) {
+ PyErr_SetString(PyExc_IndexError, "offset out of range");
+ return NULL;
+ }
+ tpl = PyTuple_New(self->key_width);
+ if (!tpl) {
+ /* Malloc failure */
+ return NULL;
+ }
+ start = offset * self->key_width;
+ for (i = 0; i < self->key_width; ++i) {
+ obj = (PyObject *)self->key_strings[start + i];
+ Py_INCREF(obj);
+ PyTuple_SET_ITEM(tpl, i, obj);
+ }
+ return tpl;
+}
+
+static char Keys_get_key_doc[] = "get_keys(offset)";
+
+
static PyMethodDef Keys_methods[] = {
+ {"get_key",
+ (PyCFunction)Keys_get_key,
+ METH_VARARGS,
+ Keys_get_key_doc},
{NULL, NULL} /* sentinel */
};
@@ -122,9 +174,7 @@
"Keys", /* tp_name */
sizeof(Keys) - sizeof(PyStringObject *), /* tp_basicsize */
sizeof(PyObject *), /* tp_itemsize */
- // We probably need a custom dealloc so that it decrefs the referenced
- // PyString objects
- 0, // (destructor)PatienceSequenceMatcher_dealloc, /* tp_dealloc */
+ (destructor)Keys_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* tp_getattr */
0, /* tp_setattr */
=== modified file 'bzrlib/tests/test__keys_type.py'
--- a/bzrlib/tests/test__keys_type.py 2009-09-08 20:43:04 +0000
+++ b/bzrlib/tests/test__keys_type.py 2009-09-08 21:06:08 +0000
@@ -16,6 +16,8 @@
"""Tests for the Keys type."""
+import sys
+
from bzrlib import (
# _keys_py,
errors,
@@ -60,7 +62,7 @@
class TestKeysType(tests.TestCase):
def test_create(self):
- t = self.module.Keys(1, 'foo', 'bar')
+ k = self.module.Keys(1, 'foo', 'bar')
def test_create_bad_args(self):
self.assertRaises(TypeError, self.module.Keys)
@@ -74,3 +76,29 @@
# too many args
self.assertRaises(ValueError, self.module.Keys, 1, *lots_of_args)
self.assertRaises(TypeError, self.module.Keys, 1, 'foo', 10)
+
+ def test_create_and_del_correct_refcount(self):
+ s = 'my custom' + ' foo bar'
+ n_ref = sys.getrefcount(s)
+ k = self.module.Keys(1, s)
+ self.assertEqual(n_ref + 1, sys.getrefcount(s))
+ del k
+ self.assertEqual(n_ref, sys.getrefcount(s))
+
+ def test_get_key(self):
+ f = 'fo' + 'o'
+ k = self.module.Keys(1, f, 'bar')
+ self.assertEqual(('foo',), k.get_key(0))
+ self.assertEqual(('bar',), k.get_key(1))
+ self.assertRaises(IndexError, k.get_key, 2)
+ n_refs = sys.getrefcount(f)
+ f_key = k.get_key(0)
+ self.assertEqual(n_refs + 1, sys.getrefcount(f))
+ del f_key
+ self.assertEqual(n_refs, sys.getrefcount(f))
+
+ def test_get_wide_key(self):
+ k = self.module.Keys(2, 'foo', 'bar', 'baz', 'bing')
+ self.assertEqual(('foo', 'bar'), k.get_key(0))
+ self.assertEqual(('baz', 'bing'), k.get_key(1))
+ self.assertRaises(IndexError, k.get_key, 2)
More information about the bazaar-commits
mailing list