Closed s-yata closed 9 years ago
まずは領域の拡張じゃなくて,最初に領域を確保するのに realloc()
を使うとどうか調べてみました.
調査に使ったコードは以下のようになっています.
int main() {
constexpr size_t SIZE = 1 << 20;
std::vector<void *> buf(SIZE);
double min_elapsed = 100.0;
for (int i = 0; i < 7; ++i) {
Timer timer;
for (int j = 0; j < SIZE; ++j) {
buf[j] = std::malloc(10);
// buf[j] = std::realloc(nullptr, 10);
}
double elapsed = timer.elapsed();
if (elapsed < min_elapsed) {
min_elapsed = elapsed;
}
for (int j = 0; j < SIZE; ++j) {
std::free(buf[j]);
}
}
std::cout << "min. elapsed [s] = " << min_elapsed << std::endl;
return 0;
}
その結果, malloc()
がおよそ 0.013 秒かかるのに対し, realloc()
は 0.015 秒程度を要しました(10bytes x 2^20 回あたり).
最初の確保だと分かっているときは, malloc()
を使う方が良さそうです.
かなり手抜きですが, malloc() + free()
と realloc()
も比較してみました.
int main() {
constexpr size_t SIZE = 1 << 20;
std::vector<void *> buf(SIZE);
double min_elapsed = 100.0;
for (int i = 0; i < 7; ++i) {
for (int j = 0; j < SIZE; ++j) {
buf[j] = std::malloc(10);
}
Timer timer;
for (int j = 0; j < SIZE; ++j) {
// void *new_buf = std::malloc(20);
// std::memcpy(new_buf, buf[j], 10);
// std::free(buf[j]);
// buf[j] = new_buf;
buf[j] = std::realloc(buf[j], 20);
}
double elapsed = timer.elapsed();
if (elapsed < min_elapsed) {
min_elapsed = elapsed;
}
for (int j = 0; j < SIZE; ++j) {
std::free(buf[j]);
}
}
std::cout << "min. elapsed [s] = " << min_elapsed << std::endl;
return 0;
}
その結果, malloc() + free()
は約 0.022 秒かかるのに対し, realloc()
は 0.014 秒で済みました.
String
については realloc()
を使うようにしました.
Array<T>
については調査が必要なので後回しにします.
Array については std::is_trivial<T>::value
が true
になるものだけ realloc()
を使うようにしました.
概要
malloc()
とfree()
を使って領域を拡張している箇所について,可能であればrealloc()
を使うように修正します. あわよくば,コピーなしで領域を拡張できるようになり,少し無駄がなくなるはずです.String
については,realloc()
を使って問題ないはずです.Array<T>
については,型によって使えるかどうかが変わります.