]> granicus.if.org Git - python/commitdiff
Issue #4445: save 3 bytes of memory (on average) per bytes allocation.
authorMark Dickinson <dickinsm@gmail.com>
Sat, 6 Dec 2008 15:33:31 +0000 (15:33 +0000)
committerMark Dickinson <dickinsm@gmail.com>
Sat, 6 Dec 2008 15:33:31 +0000 (15:33 +0000)
(This is a forward port of r67601).

Misc/NEWS
Objects/bytesobject.c

index 3dd58e6cfdcc38a38a2167321d700ed4081cf7fa..472751f09b57ed4702d0a9bc93967d385e97f057 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,11 @@ What's New in Python 3.1 alpha 0
 Core and Builtins
 -----------------
 
+- Issue #4445: Replace "sizeof(PyBytesObject)" with
+  "offsetof(PyBytesObject, ob_sval) + 1" when allocating memory for
+  bytes instances.  On a typical machine this saves 3 bytes of memory
+  (on average) per allocation of a bytes instance.
+
 - Issue #4533: File read operation was dreadfully slow due to a slowly
   growing read buffer. Fixed by using the same growth rate algorithm as
   Python 2.x.
index 76b7f522005c5c678f90b8e95989a083c3ca2f97..ca8b857cda8823ef26fb4f22cdb661a80217670d 100644 (file)
@@ -5,6 +5,7 @@
 #include "Python.h"
 
 #include "bytes_methods.h"
+#include <stddef.h>
 
 static Py_ssize_t
 _getbuffer(PyObject *obj, Py_buffer *view)
@@ -31,6 +32,14 @@ int null_strings, one_strings;
 static PyBytesObject *characters[UCHAR_MAX + 1];
 static PyBytesObject *nullstring;
 
+/* PyBytesObject_SIZE gives the basic size of a string; any memory allocation
+   for a string of length n should request PyBytesObject_SIZE + n bytes.
+
+   Using PyBytesObject_SIZE instead of sizeof(PyBytesObject) saves
+   3 bytes per string allocation on a typical system.
+*/
+#define PyBytesObject_SIZE (offsetof(PyBytesObject, ob_sval) + 1)
+
 /*
    For both PyBytes_FromString() and PyBytes_FromStringAndSize(), the
    parameter `size' denotes number of characters to allocate, not counting any
@@ -83,14 +92,14 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
                return (PyObject *)op;
        }
 
-       if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) {
+       if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
                PyErr_SetString(PyExc_OverflowError,
                                "byte string is too large");
                return NULL;
        }
 
        /* Inline PyObject_NewVar */
-       op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size);
+       op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
        if (op == NULL)
                return PyErr_NoMemory();
        PyObject_INIT_VAR(op, &PyBytes_Type, size);
@@ -117,7 +126,7 @@ PyBytes_FromString(const char *str)
 
        assert(str != NULL);
        size = strlen(str);
-       if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) {
+       if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
                PyErr_SetString(PyExc_OverflowError,
                        "byte string is too long");
                return NULL;
@@ -138,7 +147,7 @@ PyBytes_FromString(const char *str)
        }
 
        /* Inline PyObject_NewVar */
-       op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size);
+       op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
        if (op == NULL)
                return PyErr_NoMemory();
        PyObject_INIT_VAR(op, &PyBytes_Type, size);
@@ -746,13 +755,12 @@ string_repeat(register PyBytesObject *a, register Py_ssize_t n)
                return (PyObject *)a;
        }
        nbytes = (size_t)size;
-       if (nbytes + sizeof(PyBytesObject) <= nbytes) {
+       if (nbytes + PyBytesObject_SIZE <= nbytes) {
                PyErr_SetString(PyExc_OverflowError,
                        "repeated bytes are too long");
                return NULL;
        }
-       op = (PyBytesObject *)
-               PyObject_MALLOC(sizeof(PyBytesObject) + nbytes);
+       op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + nbytes);
        if (op == NULL)
                return PyErr_NoMemory();
        PyObject_INIT_VAR(op, &PyBytes_Type, size);
@@ -2803,7 +2811,7 @@ static PyObject *
 string_sizeof(PyBytesObject *v)
 {
        Py_ssize_t res;
-       res = sizeof(PyBytesObject) + Py_SIZE(v) * Py_TYPE(v)->tp_itemsize;
+       res = PyBytesObject_SIZE + Py_SIZE(v) * Py_TYPE(v)->tp_itemsize;
        return PyLong_FromSsize_t(res);
 }
 
@@ -3080,7 +3088,7 @@ static PyObject *str_iter(PyObject *seq);
 PyTypeObject PyBytes_Type = {
        PyVarObject_HEAD_INIT(&PyType_Type, 0)
        "bytes",
-       sizeof(PyBytesObject),
+       PyBytesObject_SIZE,
        sizeof(char),
        string_dealloc,                         /* tp_dealloc */
        0,                                      /* tp_print */
@@ -3175,7 +3183,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
        _Py_DEC_REFTOTAL;
        _Py_ForgetReference(v);
        *pv = (PyObject *)
-               PyObject_REALLOC((char *)v, sizeof(PyBytesObject) + newsize);
+               PyObject_REALLOC((char *)v, PyBytesObject_SIZE + newsize);
        if (*pv == NULL) {
                PyObject_Del(v);
                PyErr_NoMemory();