1

私は 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 が行うのはどれですか? そして、この種の振る舞いを制御する簡単な方法はありますか?

4

1 に答える 1

3

はい。_PyString_Resize_realloc

再割り当てを保存したい場合は、おそらくreadスタック上のバ​​ッファーに入れ、そこから文字列オブジェクトを作成することができます。次のようなもの(コンパイルおよびテストされていないため、疑似コードとして扱います):

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

また、実装の上の警告に注意してください_PyString_Resize(それは にありますObjects/stringobject.c):

次の関数は、文字列が不変であるという概念を破ります:
文字列のサイズを変更します。オブジェクトを参照するモジュールが 1 つしかない場合にのみ、これを回避します。また、新しい文字列オブジェクトを作成し、古いオブジェクトを破棄することは、より効率的であると考えることができます。いずれにせよ、文字列がコードの他の部分に既に知られている可能性がある場合は、これを使用しないでください...

于 2011-03-22T14:24:29.810 に答える