mirror of
https://github.com/scottlamb/moonfire-nvr.git
synced 2025-04-14 08:16:01 -04:00
fix up the benchmarks
These are currently the only thing which require a nightly Rust. I haven't run them since adding the feature gates. The feature gates were slightly broken, and the actual benchmarks had bitrotted a bit. Fix these things. Also put them into a separate submodule from the regular tests, so that not as many feature gates (#[cfg(feature="nightly")]) are required.
This commit is contained in:
parent
02d3bf5e39
commit
c96f306e18
@ -28,7 +28,7 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#![cfg_attr(all(nightly, test), feature(test))]
|
#![cfg_attr(all(feature="nightly", test), feature(test))]
|
||||||
|
|
||||||
extern crate byteorder;
|
extern crate byteorder;
|
||||||
extern crate core;
|
extern crate core;
|
||||||
|
101
src/mp4.rs
101
src/mp4.rs
@ -1182,19 +1182,15 @@ impl http_entity::Entity<Error> for Mp4File {
|
|||||||
/// to verify the output is byte-for-byte as expected.
|
/// to verify the output is byte-for-byte as expected.
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(nightly)] extern crate test;
|
|
||||||
|
|
||||||
use byteorder::{BigEndian, ByteOrder};
|
use byteorder::{BigEndian, ByteOrder};
|
||||||
use db;
|
use db;
|
||||||
use dir;
|
use dir;
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use ffmpeg;
|
use ffmpeg;
|
||||||
#[cfg(nightly)] use hyper;
|
|
||||||
use hyper::header;
|
use hyper::header;
|
||||||
use openssl::crypto::hash;
|
use openssl::crypto::hash;
|
||||||
use recording::{self, TIME_UNITS_PER_SEC};
|
use recording::{self, TIME_UNITS_PER_SEC};
|
||||||
use http_entity::{self, Entity};
|
use http_entity::{self, Entity};
|
||||||
#[cfg(nightly)] use self::test::Bencher;
|
|
||||||
use std::fs;
|
use std::fs;
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
@ -1205,8 +1201,7 @@ mod tests {
|
|||||||
use strutil;
|
use strutil;
|
||||||
use super::*;
|
use super::*;
|
||||||
use stream::{self, Opener, Stream};
|
use stream::{self, Opener, Stream};
|
||||||
use testutil::{self, TestDb};
|
use testutil::{self, TestDb, TEST_CAMERA_ID};
|
||||||
#[cfg(nightly)] use uuid::Uuid;
|
|
||||||
|
|
||||||
/// A wrapper around openssl's SHA-1 hashing that implements the `Write` trait.
|
/// A wrapper around openssl's SHA-1 hashing that implements the `Write` trait.
|
||||||
struct Sha1(hash::Hasher);
|
struct Sha1(hash::Hasher);
|
||||||
@ -1231,8 +1226,6 @@ mod tests {
|
|||||||
sha1.finish()
|
sha1.finish()
|
||||||
}
|
}
|
||||||
|
|
||||||
const TEST_CAMERA_ID: i32 = 1;
|
|
||||||
|
|
||||||
/// Information used within `BoxCursor` to describe a box on the stack.
|
/// Information used within `BoxCursor` to describe a box on the stack.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
struct Mp4Box {
|
struct Mp4Box {
|
||||||
@ -1436,42 +1429,8 @@ mod tests {
|
|||||||
db.syncer_channel.flush();
|
db.syncer_channel.flush();
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nightly)]
|
pub fn create_mp4_from_db(db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>, skip_90k: i32,
|
||||||
fn add_dummy_recordings_to_db(db: &db::Database) {
|
shorten_90k: i32, include_subtitles: bool) -> Mp4File {
|
||||||
let mut data = Vec::new();
|
|
||||||
data.extend_from_slice(include_bytes!("testdata/video_sample_index.bin"));
|
|
||||||
let mut db = db.lock();
|
|
||||||
let video_sample_entry_id = db.insert_video_sample_entry(1920, 1080, &[0u8; 100]).unwrap();
|
|
||||||
const START_TIME: recording::Time = recording::Time(1430006400i64 * TIME_UNITS_PER_SEC);
|
|
||||||
const DURATION: recording::Duration = recording::Duration(5399985);
|
|
||||||
let mut recording = db::RecordingToInsert{
|
|
||||||
camera_id: TEST_CAMERA_ID,
|
|
||||||
sample_file_bytes: 30104460,
|
|
||||||
flags: 0,
|
|
||||||
time: START_TIME .. (START_TIME + DURATION),
|
|
||||||
local_time: START_TIME,
|
|
||||||
video_samples: 1800,
|
|
||||||
video_sync_samples: 60,
|
|
||||||
video_sample_entry_id: video_sample_entry_id,
|
|
||||||
sample_file_uuid: Uuid::nil(),
|
|
||||||
video_index: data,
|
|
||||||
sample_file_sha1: [0; 20],
|
|
||||||
run_index: 0,
|
|
||||||
};
|
|
||||||
let mut tx = db.tx().unwrap();
|
|
||||||
tx.bypass_reservation_for_testing = true;
|
|
||||||
for _ in 0..60 {
|
|
||||||
tx.insert_recording(&recording).unwrap();
|
|
||||||
recording.time.start += DURATION;
|
|
||||||
recording.local_time += DURATION;
|
|
||||||
recording.time.end += DURATION;
|
|
||||||
recording.run_index += 1;
|
|
||||||
}
|
|
||||||
tx.commit().unwrap();
|
|
||||||
}
|
|
||||||
|
|
||||||
fn create_mp4_from_db(db: Arc<db::Database>, dir: Arc<dir::SampleFileDir>, skip_90k: i32,
|
|
||||||
shorten_90k: i32, include_subtitles: bool) -> Mp4File {
|
|
||||||
let mut builder = Mp4FileBuilder::new();
|
let mut builder = Mp4FileBuilder::new();
|
||||||
builder.include_timestamp_subtitle_track(include_subtitles);
|
builder.include_timestamp_subtitle_track(include_subtitles);
|
||||||
let all_time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
let all_time = recording::Time(i64::min_value()) .. recording::Time(i64::max_value());
|
||||||
@ -1743,6 +1702,54 @@ mod tests {
|
|||||||
fn mp4_file_slice_size() {
|
fn mp4_file_slice_size() {
|
||||||
assert_eq!(8, mem::size_of::<super::Mp4FileSlice>());
|
assert_eq!(8, mem::size_of::<super::Mp4FileSlice>());
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, feature="nightly"))]
|
||||||
|
mod bench {
|
||||||
|
extern crate test;
|
||||||
|
|
||||||
|
use db;
|
||||||
|
use hyper;
|
||||||
|
use hyper::header;
|
||||||
|
use recording::{self, TIME_UNITS_PER_SEC};
|
||||||
|
use http_entity;
|
||||||
|
use self::test::Bencher;
|
||||||
|
use std::str;
|
||||||
|
use super::tests::create_mp4_from_db;
|
||||||
|
use testutil::{self, TestDb, TEST_CAMERA_ID};
|
||||||
|
#[cfg(feature="nightly")] use uuid::Uuid;
|
||||||
|
|
||||||
|
fn add_dummy_recordings_to_db(db: &db::Database) {
|
||||||
|
let mut data = Vec::new();
|
||||||
|
data.extend_from_slice(include_bytes!("testdata/video_sample_index.bin"));
|
||||||
|
let mut db = db.lock();
|
||||||
|
let video_sample_entry_id = db.insert_video_sample_entry(1920, 1080, &[0u8; 100]).unwrap();
|
||||||
|
const START_TIME: recording::Time = recording::Time(1430006400i64 * TIME_UNITS_PER_SEC);
|
||||||
|
const DURATION: recording::Duration = recording::Duration(5399985);
|
||||||
|
let mut recording = db::RecordingToInsert{
|
||||||
|
camera_id: TEST_CAMERA_ID,
|
||||||
|
sample_file_bytes: 30104460,
|
||||||
|
flags: 0,
|
||||||
|
time: START_TIME .. (START_TIME + DURATION),
|
||||||
|
local_time_delta: recording::Duration(0),
|
||||||
|
video_samples: 1800,
|
||||||
|
video_sync_samples: 60,
|
||||||
|
video_sample_entry_id: video_sample_entry_id,
|
||||||
|
sample_file_uuid: Uuid::nil(),
|
||||||
|
video_index: data,
|
||||||
|
sample_file_sha1: [0; 20],
|
||||||
|
run_offset: 0,
|
||||||
|
};
|
||||||
|
let mut tx = db.tx().unwrap();
|
||||||
|
tx.bypass_reservation_for_testing = true;
|
||||||
|
for _ in 0..60 {
|
||||||
|
tx.insert_recording(&recording).unwrap();
|
||||||
|
recording.time.start += DURATION;
|
||||||
|
recording.time.end += DURATION;
|
||||||
|
recording.run_offset += 1;
|
||||||
|
}
|
||||||
|
tx.commit().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
/// An HTTP server for benchmarking.
|
/// An HTTP server for benchmarking.
|
||||||
/// It's used as a singleton via `lazy_static!` for two reasons:
|
/// It's used as a singleton via `lazy_static!` for two reasons:
|
||||||
@ -1757,13 +1764,11 @@ mod tests {
|
|||||||
/// Currently this only serves a single `.mp4` file but we could set up variations to benchmark
|
/// Currently this only serves a single `.mp4` file but we could set up variations to benchmark
|
||||||
/// different scenarios: with/without subtitles and edit lists, different lengths, serving
|
/// different scenarios: with/without subtitles and edit lists, different lengths, serving
|
||||||
/// different fractions of the file, etc.
|
/// different fractions of the file, etc.
|
||||||
#[cfg(nightly)]
|
|
||||||
struct BenchServer {
|
struct BenchServer {
|
||||||
url: hyper::Url,
|
url: hyper::Url,
|
||||||
generated_len: u64,
|
generated_len: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nightly)]
|
|
||||||
impl BenchServer {
|
impl BenchServer {
|
||||||
fn new() -> BenchServer {
|
fn new() -> BenchServer {
|
||||||
let mut listener = hyper::net::HttpListener::new("127.0.0.1:0").unwrap();
|
let mut listener = hyper::net::HttpListener::new("127.0.0.1:0").unwrap();
|
||||||
@ -1792,13 +1797,11 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nightly)]
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
static ref SERVER: BenchServer = { BenchServer::new() };
|
static ref SERVER: BenchServer = { BenchServer::new() };
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Benchmarks serving the generated part of a `.mp4` file (up to the first byte from disk).
|
/// Benchmarks serving the generated part of a `.mp4` file (up to the first byte from disk).
|
||||||
#[cfg(nightly)]
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn serve_generated_bytes_fresh_client(b: &mut Bencher) {
|
fn serve_generated_bytes_fresh_client(b: &mut Bencher) {
|
||||||
testutil::init();
|
testutil::init();
|
||||||
@ -1824,7 +1827,6 @@ mod tests {
|
|||||||
/// This should be faster than the `fresh` version, but see
|
/// This should be faster than the `fresh` version, but see
|
||||||
/// [this hyper issue](https://github.com/hyperium/hyper/issues/944) relating to Nagle's
|
/// [this hyper issue](https://github.com/hyperium/hyper/issues/944) relating to Nagle's
|
||||||
/// algorithm.
|
/// algorithm.
|
||||||
#[cfg(nightly)]
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn serve_generated_bytes_reuse_client(b: &mut Bencher) {
|
fn serve_generated_bytes_reuse_client(b: &mut Bencher) {
|
||||||
testutil::init();
|
testutil::init();
|
||||||
@ -1846,7 +1848,6 @@ mod tests {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(nightly)]
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn mp4_construction(b: &mut Bencher) {
|
fn mp4_construction(b: &mut Bencher) {
|
||||||
testutil::init();
|
testutil::init();
|
||||||
|
@ -419,11 +419,7 @@ impl Segment {
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
#[cfg(nightly)]
|
|
||||||
extern crate test;
|
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
#[cfg(nightly)] use self::test::Bencher;
|
|
||||||
use testutil::TestDb;
|
use testutil::TestDb;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -601,9 +597,15 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO: test segment error cases involving mismatch between row frames/key_frames and index.
|
// TODO: test segment error cases involving mismatch between row frames/key_frames and index.
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(all(test, feature="nightly"))]
|
||||||
|
mod bench {
|
||||||
|
extern crate test;
|
||||||
|
use self::test::Bencher;
|
||||||
|
use super::*;
|
||||||
|
|
||||||
/// Benchmarks the decoder, which is performance-critical for .mp4 serving.
|
/// Benchmarks the decoder, which is performance-critical for .mp4 serving.
|
||||||
#[cfg(nightly)]
|
|
||||||
#[bench]
|
#[bench]
|
||||||
fn bench_decoder(b: &mut Bencher) {
|
fn bench_decoder(b: &mut Bencher) {
|
||||||
let data = include_bytes!("testdata/video_sample_index.bin");
|
let data = include_bytes!("testdata/video_sample_index.bin");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user