mirror of
https://gitlab.isc.org/isc-projects/kea
synced 2025-08-30 13:37:55 +00:00
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
This commit is contained in:
parent
f252ae0f34
commit
94c7de226e
@ -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
|
||||
|
@ -1,33 +0,0 @@
|
||||
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
|
@ -1,388 +0,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 <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);
|
||||
}
|
@ -1,185 +0,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;
|
||||
QueryBenchMark query_bench4(*auth_server, queries, &optimized_renderer,
|
||||
true);
|
||||
BenchMark<QueryBenchMark> bench4(iteration, query_bench4);
|
||||
bench4.run();
|
||||
|
||||
delete auth_server;
|
||||
|
||||
return (0);
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
AM_CPPFLAGS = -I$(top_srcdir)/src/lib -I$(top_builddir)/src/lib
|
||||
|
||||
CLEANFILES = *.gcno *.gcda
|
||||
|
||||
noinst_PROGRAMS = buffer_bench
|
||||
buffer_bench_SOURCES = buffer_bench.cc
|
||||
buffer_bench_LDADD = $(top_builddir)/src/lib/exceptions/libexceptions.la
|
@ -1,235 +0,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 <cassert>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include <bench/benchmark.h>
|
||||
|
||||
#include <exceptions/exceptions.h>
|
||||
|
||||
#include <dns/buffer.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace isc;
|
||||
using namespace isc::dns;
|
||||
using namespace isc::bench;
|
||||
|
||||
namespace {
|
||||
// A simplified buffer implementation using plain old array for comparison
|
||||
// (omitting some validations for brevity)
|
||||
class ArrayOutputBuffer {
|
||||
public:
|
||||
ArrayOutputBuffer(size_t n) : limit_(n) {
|
||||
data_ = new uint8_t[n];
|
||||
}
|
||||
~ArrayOutputBuffer() {
|
||||
delete[] data_;
|
||||
}
|
||||
void clear() { index_ = 0; }
|
||||
void writeUint8(const uint8_t data) {
|
||||
if (index_ + 1 > limit_) {
|
||||
isc_throw(InvalidBufferPosition, "write beyond the end of buffer");
|
||||
}
|
||||
data_[index_] = data;
|
||||
++index_;
|
||||
}
|
||||
void writeUint16(const uint16_t data) {
|
||||
if (index_ + 2 > limit_) {
|
||||
isc_throw(InvalidBufferPosition, "write beyond the end of buffer");
|
||||
}
|
||||
const uint8_t net_data[2] = { (data & 0xff00U) >> 8, data & 0x00ffU };
|
||||
memcpy(&data_[index_], net_data, 2);
|
||||
index_ += 2;
|
||||
}
|
||||
void writeUint32(const uint32_t data) {
|
||||
if (index_ + 4 > limit_) {
|
||||
isc_throw(InvalidBufferPosition, "write beyond the end of buffer");
|
||||
}
|
||||
const uint8_t net_data[4] = { (data & 0xff000000) >> 24,
|
||||
(data & 0x00ff0000) >> 16,
|
||||
(data & 0x0000ff00) >> 8,
|
||||
data & 0x000000ff };
|
||||
memcpy(&data_[index_], net_data, 4);
|
||||
index_ += 4;
|
||||
}
|
||||
void writeData(const void *data, const size_t len) {
|
||||
if (len > limit_ || index_ > (limit_ - len)) {
|
||||
isc_throw(InvalidBufferPosition, "write beyond the end of buffer");
|
||||
}
|
||||
memcpy(&data_[index_], data, len);
|
||||
index_ += len;
|
||||
}
|
||||
size_t getLength() const { return (index_); }
|
||||
const void* getData() const { return (data_); }
|
||||
private:
|
||||
const size_t limit_;
|
||||
size_t index_;
|
||||
uint8_t* data_;
|
||||
};
|
||||
|
||||
const uint8_t check_data[] = {
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10, 192, 0, 2, 1,
|
||||
0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x0e, 0x10,
|
||||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 };
|
||||
|
||||
template <typename T>
|
||||
class BufferBenchMark {
|
||||
public:
|
||||
BufferBenchMark(T& buffer, const bool use_writedata) :
|
||||
buffer_(buffer), use_writedata_(use_writedata) {}
|
||||
~BufferBenchMark() {}
|
||||
unsigned int run() {
|
||||
// This test emulates writing 20 RR-like objects into the given buffer.
|
||||
buffer_.clear();
|
||||
for (int i = 0; i < 20; ++i) {
|
||||
buffer_.writeUint16(rrtype_val_);
|
||||
buffer_.writeUint16(rrclass_val_);
|
||||
buffer_.writeUint32(rrttl_val_);
|
||||
|
||||
const uint8_t* data;
|
||||
size_t datalen;
|
||||
if ((i % 2) == 0) {
|
||||
data = data_a;
|
||||
datalen = sizeof(data_a);
|
||||
} else {
|
||||
data = data_aaaa;
|
||||
datalen = sizeof(data_aaaa);
|
||||
}
|
||||
if (use_writedata_) {
|
||||
buffer_.writeData(data, datalen);
|
||||
} else {
|
||||
for (int j = 0; j < datalen; ++j) {
|
||||
buffer_.writeUint8(data[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return (1);
|
||||
}
|
||||
bool checkData() const {
|
||||
if (buffer_.getLength() < sizeof(check_data)) {
|
||||
isc_throw(Exception, "written buffer is too short: " <<
|
||||
buffer_.getLength());
|
||||
}
|
||||
if (memcmp(buffer_.getData(), check_data, sizeof(check_data)) != 0) {
|
||||
isc_throw(Exception, "data mismatch");
|
||||
}
|
||||
return (true);
|
||||
}
|
||||
bool isUsingWriteData() const { return (use_writedata_); }
|
||||
private:
|
||||
static const uint16_t rrtype_val_ = 1;
|
||||
static const uint16_t rrclass_val_ = 1;
|
||||
static const uint32_t rrttl_val_ = 3600;
|
||||
static const uint8_t data_a[4];
|
||||
static const uint8_t data_aaaa[16];
|
||||
T& buffer_;
|
||||
const bool use_writedata_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
const uint8_t BufferBenchMark<T>::data_a[] = { 192, 0, 2, 1 };
|
||||
|
||||
template <typename T>
|
||||
const uint8_t BufferBenchMark<T>::data_aaaa[] = {
|
||||
0x20, 0x01, 0x0d, 0xb8, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x12, 0x34 };
|
||||
}
|
||||
|
||||
namespace isc {
|
||||
namespace bench {
|
||||
template <>
|
||||
void
|
||||
BenchMark<BufferBenchMark<OutputBuffer> >::setUp() {
|
||||
cout << "Benchmark for write operations using libdns OutputBuffer and "
|
||||
<< (target_.isUsingWriteData() ? "writeData:" :
|
||||
"explicit loop:") << endl;
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
BenchMark<BufferBenchMark<OutputBuffer> >::tearDown() {
|
||||
assert(target_.checkData());
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
BenchMark<BufferBenchMark<ArrayOutputBuffer> >::setUp() {
|
||||
cout << "Benchmark for write operations using plain old array and "
|
||||
<< (target_.isUsingWriteData() ? "writeData:" :
|
||||
"explicit loop:") << endl;
|
||||
}
|
||||
|
||||
template <>
|
||||
void
|
||||
BenchMark<BufferBenchMark<ArrayOutputBuffer> >::tearDown() {
|
||||
assert(target_.checkData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace {
|
||||
void
|
||||
usage() {
|
||||
cerr << "Usage: buffer_bench [-n iterations]" << endl;
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char* argv[]) {
|
||||
int ch;
|
||||
int iteration = 100000;
|
||||
while ((ch = getopt(argc, argv, "n:")) != -1) {
|
||||
switch (ch) {
|
||||
case 'n':
|
||||
iteration = atoi(optarg);
|
||||
break;
|
||||
case '?':
|
||||
default:
|
||||
usage();
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
if (argc > 0) {
|
||||
usage();
|
||||
}
|
||||
|
||||
OutputBuffer dns_buffer(4096);
|
||||
BufferBenchMark<OutputBuffer> buffer_bench(dns_buffer, true);
|
||||
BenchMark<BufferBenchMark<OutputBuffer> > bench1(iteration, buffer_bench);
|
||||
bench1.run();
|
||||
|
||||
ArrayOutputBuffer array_buffer(4096);
|
||||
BufferBenchMark<ArrayOutputBuffer> array_bench(array_buffer, true);
|
||||
BenchMark<BufferBenchMark<ArrayOutputBuffer> > bench2(iteration,
|
||||
array_bench);
|
||||
bench2.run();
|
||||
|
||||
BufferBenchMark<OutputBuffer> buffer_bench2(dns_buffer, false);
|
||||
BenchMark<BufferBenchMark<OutputBuffer> > bench3(iteration, buffer_bench2);
|
||||
bench3.run();
|
||||
|
||||
BufferBenchMark<ArrayOutputBuffer> array_bench2(array_buffer, false);
|
||||
BenchMark<BufferBenchMark<ArrayOutputBuffer> > bench4(iteration,
|
||||
array_bench2);
|
||||
bench4.run();
|
||||
|
||||
return (0);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user