Commit fd24b323 authored by Mark Dickinson's avatar Mark Dickinson

Issue #4445: save 3 bytes of memory (on average) per bytes allocation.

(This is a forward port of r67601).
parent 17fe364b
...@@ -12,6 +12,11 @@ What's New in Python 3.1 alpha 0 ...@@ -12,6 +12,11 @@ What's New in Python 3.1 alpha 0
Core and Builtins 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 - Issue #4533: File read operation was dreadfully slow due to a slowly
growing read buffer. Fixed by using the same growth rate algorithm as growing read buffer. Fixed by using the same growth rate algorithm as
Python 2.x. Python 2.x.
......
...@@ -5,6 +5,7 @@ ...@@ -5,6 +5,7 @@
#include "Python.h" #include "Python.h"
#include "bytes_methods.h" #include "bytes_methods.h"
#include <stddef.h>
static Py_ssize_t static Py_ssize_t
_getbuffer(PyObject *obj, Py_buffer *view) _getbuffer(PyObject *obj, Py_buffer *view)
...@@ -31,6 +32,14 @@ int null_strings, one_strings; ...@@ -31,6 +32,14 @@ int null_strings, one_strings;
static PyBytesObject *characters[UCHAR_MAX + 1]; static PyBytesObject *characters[UCHAR_MAX + 1];
static PyBytesObject *nullstring; 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 For both PyBytes_FromString() and PyBytes_FromStringAndSize(), the
parameter `size' denotes number of characters to allocate, not counting any parameter `size' denotes number of characters to allocate, not counting any
...@@ -83,14 +92,14 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size) ...@@ -83,14 +92,14 @@ PyBytes_FromStringAndSize(const char *str, Py_ssize_t size)
return (PyObject *)op; return (PyObject *)op;
} }
if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) { if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"byte string is too large"); "byte string is too large");
return NULL; return NULL;
} }
/* Inline PyObject_NewVar */ /* Inline PyObject_NewVar */
op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size); op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
if (op == NULL) if (op == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyBytes_Type, size); PyObject_INIT_VAR(op, &PyBytes_Type, size);
...@@ -117,7 +126,7 @@ PyBytes_FromString(const char *str) ...@@ -117,7 +126,7 @@ PyBytes_FromString(const char *str)
assert(str != NULL); assert(str != NULL);
size = strlen(str); size = strlen(str);
if (size > PY_SSIZE_T_MAX - sizeof(PyBytesObject)) { if (size > PY_SSIZE_T_MAX - PyBytesObject_SIZE) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"byte string is too long"); "byte string is too long");
return NULL; return NULL;
...@@ -138,7 +147,7 @@ PyBytes_FromString(const char *str) ...@@ -138,7 +147,7 @@ PyBytes_FromString(const char *str)
} }
/* Inline PyObject_NewVar */ /* Inline PyObject_NewVar */
op = (PyBytesObject *)PyObject_MALLOC(sizeof(PyBytesObject) + size); op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + size);
if (op == NULL) if (op == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyBytes_Type, size); PyObject_INIT_VAR(op, &PyBytes_Type, size);
...@@ -746,13 +755,12 @@ string_repeat(register PyBytesObject *a, register Py_ssize_t n) ...@@ -746,13 +755,12 @@ string_repeat(register PyBytesObject *a, register Py_ssize_t n)
return (PyObject *)a; return (PyObject *)a;
} }
nbytes = (size_t)size; nbytes = (size_t)size;
if (nbytes + sizeof(PyBytesObject) <= nbytes) { if (nbytes + PyBytesObject_SIZE <= nbytes) {
PyErr_SetString(PyExc_OverflowError, PyErr_SetString(PyExc_OverflowError,
"repeated bytes are too long"); "repeated bytes are too long");
return NULL; return NULL;
} }
op = (PyBytesObject *) op = (PyBytesObject *)PyObject_MALLOC(PyBytesObject_SIZE + nbytes);
PyObject_MALLOC(sizeof(PyBytesObject) + nbytes);
if (op == NULL) if (op == NULL)
return PyErr_NoMemory(); return PyErr_NoMemory();
PyObject_INIT_VAR(op, &PyBytes_Type, size); PyObject_INIT_VAR(op, &PyBytes_Type, size);
...@@ -2803,7 +2811,7 @@ static PyObject * ...@@ -2803,7 +2811,7 @@ static PyObject *
string_sizeof(PyBytesObject *v) string_sizeof(PyBytesObject *v)
{ {
Py_ssize_t res; 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); return PyLong_FromSsize_t(res);
} }
...@@ -3080,7 +3088,7 @@ static PyObject *str_iter(PyObject *seq); ...@@ -3080,7 +3088,7 @@ static PyObject *str_iter(PyObject *seq);
PyTypeObject PyBytes_Type = { PyTypeObject PyBytes_Type = {
PyVarObject_HEAD_INIT(&PyType_Type, 0) PyVarObject_HEAD_INIT(&PyType_Type, 0)
"bytes", "bytes",
sizeof(PyBytesObject), PyBytesObject_SIZE,
sizeof(char), sizeof(char),
string_dealloc, /* tp_dealloc */ string_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
...@@ -3175,7 +3183,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize) ...@@ -3175,7 +3183,7 @@ _PyBytes_Resize(PyObject **pv, Py_ssize_t newsize)
_Py_DEC_REFTOTAL; _Py_DEC_REFTOTAL;
_Py_ForgetReference(v); _Py_ForgetReference(v);
*pv = (PyObject *) *pv = (PyObject *)
PyObject_REALLOC((char *)v, sizeof(PyBytesObject) + newsize); PyObject_REALLOC((char *)v, PyBytesObject_SIZE + newsize);
if (*pv == NULL) { if (*pv == NULL) {
PyObject_Del(v); PyObject_Del(v);
PyErr_NoMemory(); PyErr_NoMemory();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment