groonga / grnxx

groonga++
Other
7 stars 0 forks source link

領域の拡張に realloc() を使う #123

Closed s-yata closed 9 years ago

s-yata commented 9 years ago

概要

malloc()free() を使って領域を拡張している箇所について,可能であれば realloc() を使うように修正します. あわよくば,コピーなしで領域を拡張できるようになり,少し無駄がなくなるはずです.

String については, realloc() を使って問題ないはずです. Array<T> については,型によって使えるかどうかが変わります.

s-yata commented 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() を使う方が良さそうです.

s-yata commented 9 years ago

領域の拡張

かなり手抜きですが, 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 秒で済みました.

s-yata commented 9 years ago

String については realloc() を使うようにしました. Array<T> については調査が必要なので後回しにします.

s-yata commented 9 years ago

Array については std::is_trivial<T>::valuetrue になるものだけ realloc() を使うようにしました.