Commit 94c7de22 authored by JINMEI Tatuya's avatar JINMEI Tatuya
Browse files

removed additional benchmark examples for now.

updated the doxygen config to include the benchmark docs.


git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac241@2500 e5f2f494-b856-4b98-b285-d166d9295462
parent f252ae0f
......@@ -568,7 +568,7 @@ WARN_LOGFILE =
# directories like "/usr/src/myproject". Separate the files or directories
# with spaces.
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions
INPUT = ../src/lib/cc ../src/lib/config ../src/lib/dns ../src/lib/exceptions ../src/lib/bench
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
......
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
AM_CPPFLAGS += -I$(top_srcdir)/src/bin -I$(top_builddir)/src/bin
CLEANFILES = *.gcno *.gcda
noinst_PROGRAMS = query_bench
if HAVE_BOOST_SYSTEM
noinst_PROGRAMS += netio_bench
endif
query_bench_SOURCES = query_bench.cc
query_bench_SOURCES += ../auth_srv.h ../auth_srv.cc
query_bench_SOURCES += ../normalquestion.h ../normalquestion.cc
query_bench_SOURCES += ../rbt_datasrc.h ../rbt_datasrc.cc
query_bench_SOURCES += ../loadzone.h ../loadzone.cc
query_bench_LDADD = $(top_builddir)/src/lib/dns/libdns.la
query_bench_LDADD += $(top_builddir)/src/lib/exceptions/libexceptions.la
query_bench_LDADD += $(top_builddir)/src/lib/bench/libbench.la
query_bench_LDADD += $(top_builddir)/src/lib/datasrc/libdatasrc.la
query_bench_LDADD += $(top_builddir)/src/lib/config/libcfgclient.la
query_bench_LDADD += $(top_builddir)/src/lib/cc/libcc.a
query_bench_LDADD += $(SQLITE_LIBS)
if HAVE_BOOST_SYSTEM
query_bench_LDFLAGS = $(AM_LDFLAGS) $(BOOST_LDFLAGS)
query_bench_LDADD += $(BOOST_SYSTEM_LIB)
endif
if HAVE_BOOST_SYSTEM
netio_bench_SOURCES = netio_bench.cc
netio_bench_LDFLAGS = $(AM_LDFLAGS) $(BOOST_LDFLAGS)
netio_bench_LDADD = $(top_builddir)/src/lib/exceptions/.libs/libexceptions.a
netio_bench_LDADD += $(BOOST_SYSTEM_LIB)
endif
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <config.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <sys/errno.h>
#include <unistd.h>
#include <stdint.h>
#include <cstring>
#include <netdb.h>
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/asio.hpp>
#include <exceptions/exceptions.h>
#include <bench/benchmark.h>
#include <bench/benchmark_util.h>
using namespace std;
using namespace isc;
using namespace isc::bench;
using namespace boost::asio;
using ip::udp;
namespace {
class NativeSocketBenchMark {
public:
NativeSocketBenchMark(const int af, const char* const portstr,
const size_t packet_size) :
fd_(-1), packet_size_(packet_size), s_data_(packet_size),
r_data_(packet_size)
{
struct addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = af;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
int error = getaddrinfo(af == AF_INET6 ? "::1" : "127.0.0.1",
portstr, &hints, &res_);
if (error) {
isc_throw(Exception, "getaddrinfo failed: " << gai_strerror(error));
}
// XXX: for brevity the following part is intentionally exception
// unsafe.
fd_ = socket(res_->ai_family, res_->ai_socktype, res_->ai_protocol);
if (fd_ < 0) {
isc_throw(Exception, "failed to open test socket: "
<< strerror(errno));
}
if (bind(fd_, res_->ai_addr, res_->ai_addrlen) != 0) {
isc_throw(Exception, "failed to bind test socket: "
<< strerror(errno));
}
maxfd_ = fd_ + 1;
FD_ZERO(&readfds_);
FD_SET(fd_, &readfds_);
}
~NativeSocketBenchMark() {
if (fd_ >= 0) {
close(fd_);
}
freeaddrinfo(res_);
}
void closeSocket() {
if (fd_ >= 0) {
close(fd_);
}
fd_ = -1;
}
unsigned int run() {
const int cc_s = sendto(fd_, &s_data_[0], s_data_.size(), 0,
res_->ai_addr, res_->ai_addrlen);
if (cc_s != packet_size_) {
isc_throw(Exception, "sendto failed, return value=" << cc_s);
}
fd_set readfds = readfds_;
const int n = select(maxfd_, &readfds, NULL, NULL, NULL);
if (n != 1 || !FD_ISSET(fd_, &readfds)) {
isc_throw(Exception, "unexpected result from select, return value="
<< n);
}
struct sockaddr* from = reinterpret_cast<struct sockaddr*>(&ss_);
socklen_t from_len = sizeof(ss_);
r_data_.clear();
const int cc_r = recvfrom(fd_, &r_data_[0], r_data_.capacity(), 0, from,
&from_len);
if (cc_r != packet_size_) {
isc_throw(Exception, "recvfrom failed, return value=" << cc_r);
}
return (1);
}
private:
int fd_;
int maxfd_;
const size_t packet_size_;
struct addrinfo* res_;
vector<uint8_t> s_data_;
vector<uint8_t> r_data_;
fd_set readfds_;
struct sockaddr_storage ss_;
};
class ASIOBenchMark {
public:
ASIOBenchMark(io_service& io_service, const int af, const uint16_t portnum,
const size_t packet_size) :
packet_size_(packet_size),
io_service_(io_service),
socket_(io_service, af == AF_INET6 ? udp::v6() : udp::v4()),
s_data_(packet_size), r_data_(packet_size),
endpoint_(af == AF_INET6 ? udp::v6() : udp::v4(), portnum)
{
endpoint_.address(ip::address::from_string(
af == AF_INET6 ? "::1" : "127.0.0.1"));
socket_.bind(endpoint_);
}
unsigned int run() {
isc_throw(Exception, "test is performed for a base class");
}
void cleanup() {
socket_.close();
io_service_.reset();
}
protected:
const size_t packet_size_;
io_service& io_service_;
udp::socket socket_;
vector<uint8_t> s_data_;
vector<uint8_t> r_data_;
udp::endpoint endpoint_;
udp::endpoint sender_endpoint_;
boost::system::error_code serror_;
};
class ASIOSyncBenchMark : public ASIOBenchMark {
public:
ASIOSyncBenchMark(io_service& io_service, const int af,
const uint16_t portnum, const size_t packet_size) :
ASIOBenchMark(io_service, af, portnum, packet_size),
fd_(socket_.native()), maxfd_(fd_ + 1)
{
FD_ZERO(&readfds_);
FD_SET(fd_, &readfds_);
}
unsigned int run() {
const size_t cc_s = socket_.send_to(
boost::asio::buffer(&s_data_[0], s_data_.size()),
endpoint_, 0, serror_);
if (cc_s != packet_size_ || serror_) {
isc_throw(Exception, "asio::send_to failed, return value="
<< cc_s);
}
// add the overhead of select for fair comparison
fd_set readfds = readfds_;
const int n = select(maxfd_, &readfds, NULL, NULL, NULL);
if (n != 1 || !FD_ISSET(fd_, &readfds)) {
isc_throw(Exception, "unexpected result from select, return value="
<< n);
}
r_data_.clear();
const size_t cc_r = socket_.receive_from(
boost::asio::buffer(&r_data_[0], r_data_.capacity()),
sender_endpoint_);
if (cc_r != packet_size_) {
isc_throw(Exception, "asio::receive_from failed, return value="
<< cc_r);
}
return (1);
}
private:
const int fd_;
const int maxfd_;
fd_set readfds_;
};
class ASIOAsyncBenchMark : public ASIOBenchMark {
public:
ASIOAsyncBenchMark(io_service& io_service, const int af,
const uint16_t portnum, const size_t packet_size,
const unsigned int iteration, const bool async_send) :
ASIOBenchMark(io_service, af, portnum, packet_size),
iteration_(iteration), n_received_(0), async_send_(async_send)
{}
unsigned int run() {
if (!async_send_) {
startReceive();
}
sendTo();
io_service_.run();
return (iteration_);
}
private:
void sendTo() {
if (async_send_) {
socket_.async_send_to(
boost::asio::buffer(&s_data_[0], s_data_.size()),
endpoint_,
boost::bind(&ASIOAsyncBenchMark::sendCompleted, this,
placeholders::error,
placeholders::bytes_transferred));
} else {
const size_t cc_s = socket_.send_to(
boost::asio::buffer(&s_data_[0], s_data_.size()),
endpoint_, 0, serror_);
if (cc_s != packet_size_ || serror_) {
isc_throw(Exception, "asio::send_to failed, return value="
<< cc_s);
}
}
}
void handleReceive(const boost::system::error_code& error,
size_t bytes_recvd)
{
if (error || bytes_recvd != packet_size_) {
isc_throw(Exception, "asio::asyncronous receive failed: "
<< error << ", #received=" << bytes_recvd);
}
if (++n_received_ == iteration_) {
io_service_.stop();
} else {
sendTo();
if (!async_send_) {
startReceive();
}
}
}
void startReceive() {
socket_.async_receive_from(
boost::asio::buffer(&r_data_[0], r_data_.capacity()),
sender_endpoint_,
boost::bind(&ASIOAsyncBenchMark::handleReceive, this,
placeholders::error,
placeholders::bytes_transferred));
}
void sendCompleted(const boost::system::error_code& error UNUSED_PARAM,
size_t bytes_sent UNUSED_PARAM)
{
// ignore possible errors and just keep receiving.
startReceive();
}
private:
const unsigned int iteration_;
unsigned int n_received_;
const bool async_send_;
};
}
namespace isc {
namespace bench {
template<>
void
BenchMark<NativeSocketBenchMark>::tearDown() {
target_.closeSocket();
}
template<>
void
BenchMark<ASIOSyncBenchMark>::tearDown() {
target_.cleanup();
}
template<>
void
BenchMark<ASIOAsyncBenchMark>::tearDown() {
target_.cleanup();
}
}
}
namespace {
const int DEFAULT_PACKET_SIZE = 250; // arbitrary choice
const int DEFAULT_ITERATION = 10000;
const char* const DEFAULT_PORTSTR = "53530";
void
usage() {
cerr << "Usage: netio_bench [-n iterations] [-p port] [-s packet_size]"
<< endl;
exit (1);
}
}
int
main(int argc, char* argv[]) {
int ch;
int iteration = DEFAULT_ITERATION;
int packet_size = DEFAULT_PACKET_SIZE;
const char* portstr = DEFAULT_PORTSTR;
while ((ch = getopt(argc, argv, "n:p:s:")) != -1) {
switch (ch) {
case 'n':
iteration = atoi(optarg);
break;
case 'p':
portstr = optarg;
break;
case 's':
packet_size = atoi(optarg);
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc > 0) {
usage();
}
boost::asio::io_service io_service;
const uint16_t portnum = static_cast<uint16_t>(atoi(portstr));
cout << "Socket I/O benchmark using native socket API (IPv4)" << endl;
NativeSocketBenchMark io_bench1(AF_INET, portstr, packet_size);
BenchMark<NativeSocketBenchMark> bench1(iteration, io_bench1);
bench1.run();
cout << "Socket I/O benchmark using native socket API (IPv6)" << endl;
NativeSocketBenchMark io_bench2(AF_INET6, portstr, packet_size);
BenchMark<NativeSocketBenchMark> bench2(iteration, io_bench2);
bench2.run();
cout << "ASIO benchmark using synchronous I/O (IPv4)" << endl;
ASIOSyncBenchMark io_bench3(io_service, AF_INET, portnum, packet_size);
BenchMark<ASIOSyncBenchMark> bench3(iteration, io_bench3);
bench3.run();
cout << "ASIO benchmark using synchronous I/O (IPv6)" << endl;
ASIOSyncBenchMark io_bench4(io_service, AF_INET6, portnum, packet_size);
BenchMark<ASIOSyncBenchMark> bench4(iteration, io_bench4);
bench4.run();
cout << "ASIO benchmark using asynchronous receive I/O (IPv4)" << endl;
ASIOAsyncBenchMark io_bench5(io_service, AF_INET, portnum, packet_size,
iteration, false);
BenchMark<ASIOAsyncBenchMark> bench5(1, io_bench5);
bench5.run();
cout << "ASIO benchmark using asynchronous receive I/O (IPv6)" << endl;
ASIOAsyncBenchMark io_bench6(io_service, AF_INET6, portnum, packet_size,
iteration, false);
BenchMark<ASIOAsyncBenchMark> bench6(1, io_bench6);
bench6.run();
cout << "ASIO benchmark using asynchronous send/receive I/O (IPv4)" << endl;
ASIOAsyncBenchMark io_bench7(io_service, AF_INET, portnum, packet_size,
iteration, true);
BenchMark<ASIOAsyncBenchMark> bench7(1, io_bench7);
bench7.run();
cout << "ASIO benchmark using asynchronous send/receive I/O (IPv6)" << endl;
ASIOAsyncBenchMark io_bench8(io_service, AF_INET6, portnum, packet_size,
iteration, true);
BenchMark<ASIOAsyncBenchMark> bench8(1, io_bench8);
bench8.run();
return (0);
}
// Copyright (C) 2010 Internet Systems Consortium, Inc. ("ISC")
//
// Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted, provided that the above
// copyright notice and this permission notice appear in all copies.
//
// THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
// AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
// OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
// PERFORMANCE OF THIS SOFTWARE.
// $Id$
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <iostream>
#include <vector>
#include <bench/benchmark.h>
#include <bench/benchmark_util.h>
#include <dns/buffer.h>
#include <dns/message.h>
#include <dns/messagerenderer.h>
#include <dns/name.h>
#include <dns/question.h>
#include <dns/rrclass.h>
#include <auth/auth_srv.h>
#include <auth/rbt_datasrc.h>
#include <auth/loadzone.h>
using namespace std;
using namespace isc;
using namespace isc::dns;
using namespace isc::bench;
namespace {
class QueryBenchMark {
public:
QueryBenchMark(AuthSrv& server, const BenchQueries& queries,
MessageRenderer* renderer, const bool need_to_write) :
server_(server), queries_(queries), query_message_(Message::PARSE),
renderer_(renderer), null_fd_(-1), need_to_write_(need_to_write)
{
null_fd_ = open("/dev/null", O_RDWR);
if (null_fd_ < 0) {
isc_throw(Exception, "failed to open output file");
}
}
~QueryBenchMark() {
if (null_fd_ >= 0) {
close(null_fd_);
}
}
unsigned int run() {
BenchQueries::const_iterator query;
const BenchQueries::const_iterator query_end = queries_.end();
for (query = queries_.begin(); query != query_end; ++query) {
InputBuffer buffer(&(*query)[0], (*query).size());
query_message_.clear(Message::PARSE);
renderer_->clear();
server_.processMessage(buffer, query_message_, *renderer_, true);
if (need_to_write_) {
write(null_fd_, renderer_->getData(), renderer_->getLength());
}
}
return (queries_.size());
}
private:
AuthSrv& server_;
const BenchQueries& queries_;
Message query_message_;
MessageRenderer* renderer_;
int null_fd_;
const bool need_to_write_;
};
}
namespace isc {
namespace bench {
template<>
void
BenchMark<QueryBenchMark>::printResult() const {
cout.precision(6);
cout << "Processed " << getIteration() << " queries in "
<< fixed << getDuration() << "s";
cout.precision(2);
cout << " (" << fixed << getIterationPerSecond() << "qps)" << endl;
}
}
}
namespace {
void
usage() {
cerr << "Usage: query_bench [-n iterations] zone_file "
"zone_origin query_datafile" << endl;
exit (1);
}
}
int
main(int argc, char* argv[]) {
int ch;
int iteration = 1;
while ((ch = getopt(argc, argv, "n:")) != -1) {
switch (ch) {
case 'n':
iteration = atoi(optarg);
break;
case '?':
default:
usage();
}
}
argc -= optind;
argv += optind;
if (argc < 3) {
usage();
}
const char* const zone_file = argv[0];
const char* const origin = argv[1];
const char* const query_data_file = argv[2];
// Prepare the database
RbtDataSrc* datasrc = new RbtDataSrc(Name(origin));
loadZoneFile(zone_file, datasrc);
// Load queries
BenchQueries queries;
loadQueryData(query_data_file, queries, RRClass::IN());
// Create server object.
// The current experimental implementation depends on some environment
// variables, so we configure them before constructing a new server.
setenv("ZONEFILE", zone_file, 1);
setenv("DBORIGIN", origin, 1);
AuthSrv* auth_server = new AuthSrv;
// Create different types of message renderer
CompressOffsetTable offset_table_;
OutputBuffer buffer(4096);
MessageRenderer standard_renderer(buffer, &offset_table_);
MessageRenderer optimized_renderer(4096, &offset_table_);
// Perform benchmark test and dump the result
cout << "Query processing benchmark with standard renderer, "
"no write to device " << endl;
QueryBenchMark query_bench1(*auth_server, queries, &standard_renderer,
false);
BenchMark<QueryBenchMark> bench1(iteration, query_bench1);
bench1.run();
cout << "Query processing benchmark with standard renderer, "
"write to device " << endl;
QueryBenchMark query_bench2(*auth_server, queries, &standard_renderer,
true);
BenchMark<QueryBenchMark> bench2(iteration, query_bench2);
bench2.run();
cout << "Query processing benchmark with optimized renderer, "
"no write to device " << endl;
QueryBenchMark query_bench3(*auth_server, queries, &optimized_renderer,
false);
BenchMark<QueryBenchMark> bench3(iteration, query_bench3);
bench3.run();
cout << "Query processing benchmark with optimized renderer, "
"write to device " << endl;