moonfire-nvr/src/recording-bench.cc
Scott Lamb 0aadf227c1 Benchmark & speed up SampleIndexIterator
I'm seeing what is possible performance-wise in the current C++ before
trying out Go and Rust implementations.

* use the google benchmark framework and some real data.

* use release builds - I hadn't done this in a while, and there were a
  few compile errors that manifested only in release mode. Update the
  readme to suggest using a release build.

* optimize the varint decoder and SampleIndexIterator to branch less.

* enable link-time optimization for release builds.

* add some support for feedback-directed optimization. Ideally "make"
  would automatically produce the "generate" build outputs with a
  different object/library/executable suffix, run the generate
  benchmark, and then produce the "use" builds. This is not that fancy;
  you have to run an arcane command:

  alias cmake='cmake -DCMAKE_BUILD_TYPE=Release'
  cmake -DPROFILE_GENERATE=true -DPROFILE_USE=false .. && \
  make recording-bench && \
  src/recording-bench && \
  cmake -DPROFILE_GENERATE=false -DPROFILE_USE=true .. && \
  make recording-bench && \
  perf stat -e cycles,instructions,branches,branch-misses \
      src/recording-bench --benchmark_repetitions=5

  That said, the results are dramatic - at least 50% improvement. (The
  results weren't stable before as small tweaks to the code caused a
  huge shift in performance, presumably something something branch
  alignment something something.)
2016-05-19 22:53:23 -07:00

67 lines
2.5 KiB
C++

// This file is part of Moonfire NVR, a security camera network video recorder.
// Copyright (C) 2016 Scott Lamb <slamb@slamb.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// In addition, as a special exception, the copyright holders give
// permission to link the code of portions of this program with the
// OpenSSL library under certain conditions as described in each
// individual source file, and distribute linked combinations including
// the two.
//
// You must obey the GNU General Public License in all respects for all
// of the code used other than OpenSSL. If you modify file(s) with this
// exception, you may extend this exception to your version of the
// file(s), but you are not obligated to do so. If you do not wish to do
// so, delete this exception statement from your version. If you delete
// this exception statement from all source files in the program, then
// also delete it here.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// recording-bench.cc: benchmarks of the recording.h interface.
#include <benchmark/benchmark.h>
#include <gflags/gflags.h>
#include "recording.h"
#include "testutil.h"
DECLARE_bool(alsologtostderr);
static void BM_Iterator(benchmark::State &state) {
using moonfire_nvr::ReadFileOrDie;
using moonfire_nvr::SampleIndexIterator;
// state.PauseTiming();
std::string index = ReadFileOrDie("../src/testdata/video_sample_index.bin");
// state.ResumeTiming();
while (state.KeepRunning()) {
SampleIndexIterator it(index);
while (!it.done()) it.Next();
CHECK(!it.has_error()) << it.error();
}
state.SetBytesProcessed(int64_t(state.iterations()) * int64_t(index.size()));
}
BENCHMARK(BM_Iterator);
int main(int argc, char **argv) {
FLAGS_alsologtostderr = true;
// Sadly, these two flag-parsing libraries don't appear to get along.
// google::ParseCommandLineFlags(&argc, &argv, true);
benchmark::Initialize(&argc, argv);
google::InitGoogleLogging(argv[0]);
benchmark::RunSpecifiedBenchmarks();
return 0;
}