mirror of https://github.com/python/cpython
Issue #4445: save 3 bytes of memory (on average) per bytes allocation.
(This is a forward port of r67601).
This commit is contained in:
parent
17fe364b44
commit
fd24b323f9
|
@ -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 @@
|
||||||
#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;
|
||||||
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)
|
||||||
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)
|
||||||
|
|
||||||
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)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 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)
|
||||||
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 *
|
||||||
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);
|
||||||
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)
|
||||||
_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();
|
||||||
|
|
Loading…
Reference in New Issue