Skip to content

Commit

Permalink
initial benchmarks
Browse files Browse the repository at this point in the history
  • Loading branch information
bluejekyll committed Nov 27, 2016
1 parent cbfa7be commit 1f41d66
Show file tree
Hide file tree
Showing 4 changed files with 281 additions and 8 deletions.
49 changes: 49 additions & 0 deletions server/benches/bind_conf/example.conf
@@ -0,0 +1,49 @@
/*
* Copyright (C) 2014, 2016 Internet Systems Consortium, Inc. ("ISC")
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/

/* Trust-DNS bench setup: this is meant to mimic the trust-dns-server config
which is in tests/named_test_configs/example.toml */

controls { /* empty */ };

options {
pid-file "/tmp/named.pid";
listen-on { 127.0.0.1; };
listen-on-v6 { none; };
recursion no;
};

zone "localhost" {
type master;
file "../../server/tests/named_test_configs/default/localhost.zone";
};

zone "0.0.127.in-addr.arpa" {
type master;
file "../../server/tests/named_test_configs/default/127.0.0.1.zone";
};

zone "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" {
type master;
file "../../server/tests/named_test_configs/default/ipv6_1.zone";
};

zone "255.in-addr.arpa" {
type master;
file "../../server/tests/named_test_configs/default/255.zone";
};

zone "0.in-addr.arpa" {
type master;
file "../../server/tests/named_test_configs/default/0.zone";
};

zone "example.com" {
type master;
file "../../server/tests/named_test_configs/example.com.zone";
};
222 changes: 222 additions & 0 deletions server/benches/comparison_benches.rs
@@ -0,0 +1,222 @@
#![feature(test)]

extern crate futures;
extern crate test;
extern crate tokio_core;

extern crate trust_dns;
extern crate trust_dns_server;

use std::fs::DirBuilder;
use std::env;
use std::io::{BufRead, BufReader, Read, stdout, Write};
use std::mem;
use std::net::{Ipv4Addr, SocketAddr, ToSocketAddrs};
use std::path::Path;
use std::process::{Child, Command, Stdio};
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use std::thread;

use test::Bencher;
use tokio_core::reactor::Core;

use trust_dns::client::*;
use trust_dns::op::*;
use trust_dns::rr::*;
use trust_dns::udp::*;
use trust_dns::tcp::*;

fn find_test_port() -> u16 {
let server = std::net::UdpSocket::bind(("0.0.0.0", 0)).unwrap();
let server_addr = server.local_addr().unwrap();
server_addr.port()
}

struct NamedProcess{ named: Child, thread_notice: Arc<AtomicBool> }

impl Drop for NamedProcess {
fn drop(&mut self) {
self.named.kill().expect("could not kill process");
self.named.wait().expect("waiting failed");

self.thread_notice.store(true, Ordering::Relaxed);
}
}

fn wrap_process<R>(named: Child, io: R, started_str: &str) -> NamedProcess where R: Read + Send + 'static {
let mut named_out = BufReader::new(io);

// we should get the correct output before 1000 lines...
let mut output = String::new();
let mut found = false;
for _ in 0..1000 {
output.clear();
named_out.read_line(&mut output).expect("could not read stdout");
// stdout().write(b"SRV: ").unwrap();
// stdout().write(output.as_bytes()).unwrap();
if output.ends_with(started_str) { found = true; break }
}

stdout().flush().unwrap();
assert!(found, "server did not startup...");

let thread_notice = Arc::new(AtomicBool::new(false));
let thread_notice_clone = thread_notice.clone();

thread::Builder::new().name("named stdout".into()).spawn(move ||{
let thread_notice = thread_notice_clone;
while !thread_notice.load(std::sync::atomic::Ordering::Relaxed) {
output.clear();
named_out.read_line(&mut output).expect("could not read stdout");
// stdout().write(b"SRV: ").unwrap();
// stdout().write(output.as_bytes()).unwrap();
}
}).expect("no thread available");

// return handle to child process
NamedProcess{ named: named, thread_notice: thread_notice }
}

/// Returns a NamedProcess (cleans the process up on drop), and a socket addr for connecting
/// to the server.
fn trust_dns_process() -> (NamedProcess, u16) {
// find a random port to listen on
let test_port = find_test_port();

let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or(".".to_owned());

let mut named = Command::new(&format!("{}/../target/debug/named", server_path))
.stdout(Stdio::piped())
.arg("-q")
.arg(&format!("--config={}/tests/named_test_configs/example.toml", server_path))
.arg(&format!("--zonedir={}/tests/named_test_configs", server_path))
.arg(&format!("--port={}", test_port))
.spawn()
.expect("failed to start named");
//

let stdout = mem::replace(&mut named.stdout, None).unwrap();
let process = wrap_process(named, stdout, "awaiting connections...\n");
// return handle to child process
(process, test_port)
}

/// Runs the bench tesk using the specified client
fn bench(b: &mut Bencher, io_loop: &mut Core, client: &mut BasicClientHandle) {
let name = domain::Name::with_labels(vec!["www".to_string(), "example".to_string(), "com".to_string()]);

// validate the request
let response = io_loop.run(client.query(name.clone(), DNSClass::IN, RecordType::A));
assert!(!response.is_err(), "request failed: {}", response.unwrap_err());

let response = response.unwrap();
assert_eq!(response.get_response_code(), ResponseCode::NoError);

let record = &response.get_answers()[0];
if let &RData::A(ref address) = record.get_rdata() {
assert_eq!(address, &Ipv4Addr::new(127,0,0,1));
} else {
assert!(false);
}

b.iter(|| {
let response = io_loop.run(client.query(name.clone(), DNSClass::IN, RecordType::A));
response.unwrap()
});
}


#[bench]
fn trust_dns_udp_bench(b: &mut Bencher) {
let (named, server_port) = trust_dns_process();

let mut io_loop = Core::new().unwrap();
let addr: SocketAddr = ("127.0.0.1", server_port).to_socket_addrs().unwrap().next().unwrap();
let (stream, sender) = UdpClientStream::new(addr, io_loop.handle());
let mut client = ClientFuture::new(stream, sender, io_loop.handle(), None);

bench(b, &mut io_loop, &mut client);

// cleaning up the named process
drop(named);
}

#[bench]
fn trust_dns_tcp_bench(b: &mut Bencher) {
let (named, server_port) = trust_dns_process();

let mut io_loop = Core::new().unwrap();
let addr: SocketAddr = ("127.0.0.1", server_port).to_socket_addrs().unwrap().next().unwrap();
let (stream, sender) = TcpClientStream::new(addr, io_loop.handle());
let mut client = ClientFuture::new(stream, sender, io_loop.handle(), None);

bench(b, &mut io_loop, &mut client);

// cleaning up the named process
drop(named);
}

// downloaded from https://www.isc.org/downloads/file/bind-9-11-0-p1/
// cd bind-9-11-0-p1
// .configure
// make
// export TDNS_BIND_PATH=${PWD}/bin/named/named
fn bind_process() -> (NamedProcess, u16) {
let test_port = find_test_port();

let bind_path = env::var("TDNS_BIND_PATH").unwrap_or("bind".to_owned());
let server_path = env::var("TDNS_SERVER_SRC_ROOT").unwrap_or(".".to_owned());

// create the work directory
let working_dir = format!("{}/../target/bind_pwd", server_path);
if !Path::new(&working_dir).exists() {
DirBuilder::new().create(&working_dir).expect("failed to create dir");
}

let mut named = Command::new(bind_path)
.current_dir(&working_dir)
.stderr(Stdio::piped())
.arg("-c").arg(&format!("../../server/benches/bind_conf/example.conf"))
//.arg("-d").arg("0")
.arg("-D").arg("TRust-DNS cmp bench")
.arg("-g")
.arg("-p").arg(&format!("{}", test_port))
.spawn()
.expect("failed to start named");

//
let stderr = mem::replace(&mut named.stderr, None).unwrap();
let process = wrap_process(named, stderr, "running\n");
(process, test_port)
}

#[bench]
fn bind_udp_bench(b: &mut Bencher) {
let (named, server_port) = bind_process();

let mut io_loop = Core::new().unwrap();
let addr: SocketAddr = ("127.0.0.1", server_port).to_socket_addrs().unwrap().next().unwrap();
let (stream, sender) = UdpClientStream::new(addr, io_loop.handle());
let mut client = ClientFuture::new(stream, sender, io_loop.handle(), None);

bench(b, &mut io_loop, &mut client);

// cleaning up the named process
drop(named);
}

#[bench]
fn bind_tcp_bench(b: &mut Bencher) {
let (named, server_port) = bind_process();

let mut io_loop = Core::new().unwrap();
let addr: SocketAddr = ("127.0.0.1", server_port).to_socket_addrs().unwrap().next().unwrap();
let (stream, sender) = TcpClientStream::new(addr, io_loop.handle());
let mut client = ClientFuture::new(stream, sender, io_loop.handle(), None);

bench(b, &mut io_loop, &mut client);

// cleaning up the named process
drop(named);
}
17 changes: 9 additions & 8 deletions server/src/named.rs
Expand Up @@ -63,6 +63,7 @@ use trust_dns_server::server::ServerFuture;

// the Docopt usage string.
// http://docopt.org
// TODO: add option for specifying list of addresses instead of just port.
const USAGE: &'static str = "
Usage: named [options]
named (-h | --help | --version)
Expand Down Expand Up @@ -273,7 +274,7 @@ pub fn main() {
}

banner();
info!("awaiting connections...");
println!("awaiting connections...");
if let Err(e) = server.listen() {
error!("failed to listen: {}", e);
}
Expand All @@ -283,11 +284,11 @@ pub fn main() {
}

fn banner() {
println!("");
println!(" o o o ");
println!(" | | | ");
println!(" -o- o-o o o o-o -o- o-o o-O o-o o-o ");
println!(" | | | | \\ | | | | | \\ ");
println!(" o o o--o o-o o o-o o o o-o ");
println!("");
info!("");
info!(" o o o ");
info!(" | | | ");
info!(" --O-- o-o o o o-o --O-- o-o o-O o-o o-o ");
info!(" | | | | \\ | | | | | \\ ");
info!(" o o o--o o-o o o-o o o o-o ");
info!("");
}
1 change: 1 addition & 0 deletions server/src/server/server.rs
Expand Up @@ -219,6 +219,7 @@ impl DnsHandler for TcpListener {
}
}

#[allow(unreachable_code)] // this has been deprecated
impl DnsHandler for (UdpSocket, VecDeque<UdpHandler>) {
fn handle(&mut self, events: EventSet, catalog: &Arc<Catalog>) -> (Option<EventSet>, Option<(DnsHandlerType, EventSet)>) {
let ref socket = self.0;
Expand Down

0 comments on commit 1f41d66

Please sign in to comment.