_PyString_Resize реаллок памяти? - PullRequest
1 голос
/ 22 марта 2011

Я работаю над модулем расширения Python C (для CPython 2.5).Он вызывает некоторый базовый сетевой API, который заполняет буфер.

В настоящее время код написан в основном следующим образом:

PyObject * buffer;
char * cbuf;
size_t buffer_size = 1024;
int sz;
buffer = PyString_FromStringAndSize(NULL, buffer_size);
if (buffer == NULL) return NULL;
cbuf = PyString_AsString(buffer);
Py_BEGIN_ALLOW_THREADS
sz = read(cbuf, buffer_size);
Py_END_ALLOW_THREADS
if (sz > 0 &&  sz != buffer_size && _PyString_Resize(&buffer, sz) < 0)
        return NULL;

Насколько я знаю, этот код работает нормально, но мне интересновнутренние органы _PyString_Resize.Если sz меньше, чем buffer_size, использует ли он существующий буфер или перераспределяет память?

С точки зрения эффективности я, вероятно, предпочел бы, чтобы первый избегал бесполезной копии содержимого буфера, даже если он потребляет больше памяти, чем необходимо.С другой стороны, перераспределение памяти также может иметь смысл уменьшить объем занимаемой памяти.

Так что же делает _PyString_Resize?И есть ли простой способ контролировать такое поведение?

1 Ответ

3 голосов
/ 22 марта 2011

Да, _PyString_Resize делает realloc - в конце концов, это то, что вы просили это сделать: -)

Если вы хотите сохранить перераспределение, возможно, вы можете read в буфер в стеке, а затем просто создать из него строковый объект. Что-то вроде (не скомпилировано и не протестировано, поэтому рассматривайте это как псевдокод):

char cbuf[BUFFER_SIZE];
int sz = read(cbuf, BUFFER_SIZE);
PyObject * buffer = PyString_FromStringAndSize(cbuf, sz);

Также обратите внимание на предупреждение над реализацией _PyString_ResizeObjects/stringobject.c):

Следующая функция нарушает представление о том, что строки являются неизменяемыми:
это изменяет размер строки. Мы сойти с рук, только если есть только один модуль, ссылающийся на объект. Вы также можете думать об этом как о создании нового строкового объекта и уничтожая старый, только эффективнее. В любом случае не используйте это если строка уже может быть известна какой-то другой части кода ...

...