|
@@ -33,6 +33,7 @@
|
|
|
#include <xfr/xfrout_client.h>
|
|
|
|
|
|
#include <auth/auth_srv.h>
|
|
|
+#include <auth/config.h>
|
|
|
#include <auth/query.h>
|
|
|
|
|
|
#include <asiolink/asiolink.h>
|
|
@@ -53,24 +54,25 @@ XfroutClient xfrout_client("dummy_path"); // path doesn't matter
|
|
|
// Just something to pass as the server to resume
|
|
|
class DummyServer : public DNSServer {
|
|
|
public:
|
|
|
- virtual void operator()(asio::error_code, size_t) { }
|
|
|
- virtual void resume(const bool) { }
|
|
|
+ virtual void operator()(asio::error_code, size_t) {}
|
|
|
+ virtual void resume(const bool) {}
|
|
|
virtual DNSServer* clone() {
|
|
|
- return new DummyServer(*this);
|
|
|
+ return (new DummyServer(*this));
|
|
|
}
|
|
|
};
|
|
|
|
|
|
class QueryBenchMark {
|
|
|
-private:
|
|
|
+protected:
|
|
|
// Maintain dynamically generated objects via shared pointers because
|
|
|
// QueryBenchMark objects will be copied.
|
|
|
typedef boost::shared_ptr<AuthSrv> AuthSrvPtr;
|
|
|
+private:
|
|
|
typedef boost::shared_ptr<const IOEndpoint> IOEndpointPtr;
|
|
|
-public:
|
|
|
- QueryBenchMark(const int cache_slots, const char* const datasrc_file,
|
|
|
+protected:
|
|
|
+ QueryBenchMark(const bool enable_cache,
|
|
|
const BenchQueries& queries, MessagePtr query_message,
|
|
|
OutputBufferPtr buffer) :
|
|
|
- server_(new AuthSrv(cache_slots >= 0 ? true : false, xfrout_client)),
|
|
|
+ server_(new AuthSrv(enable_cache, xfrout_client)),
|
|
|
queries_(queries),
|
|
|
query_message_(query_message),
|
|
|
buffer_(buffer),
|
|
@@ -78,13 +80,8 @@ public:
|
|
|
dummy_endpoint(IOEndpointPtr(IOEndpoint::create(IPPROTO_UDP,
|
|
|
IOAddress("192.0.2.1"),
|
|
|
5300)))
|
|
|
- {
|
|
|
- if (cache_slots >= 0) {
|
|
|
- server_->setCacheSlots(cache_slots);
|
|
|
- }
|
|
|
- server_->updateConfig(Element::fromJSON("{\"database_file\": \"" +
|
|
|
- string(datasrc_file) + "\"}"));
|
|
|
- }
|
|
|
+ {}
|
|
|
+public:
|
|
|
unsigned int run() {
|
|
|
BenchQueries::const_iterator query;
|
|
|
const BenchQueries::const_iterator query_end = queries_.end();
|
|
@@ -93,14 +90,16 @@ public:
|
|
|
IOMessage io_message(&(*query)[0], (*query).size(), dummy_socket,
|
|
|
*dummy_endpoint);
|
|
|
query_message_->clear(Message::PARSE);
|
|
|
+ buffer_->clear();
|
|
|
server_->processMessage(io_message, query_message_, buffer_,
|
|
|
- &server);
|
|
|
+ &server);
|
|
|
}
|
|
|
|
|
|
return (queries_.size());
|
|
|
}
|
|
|
-private:
|
|
|
+protected:
|
|
|
AuthSrvPtr server_;
|
|
|
+private:
|
|
|
const BenchQueries& queries_;
|
|
|
MessagePtr query_message_;
|
|
|
OutputBufferPtr buffer_;
|
|
@@ -108,26 +107,92 @@ private:
|
|
|
IOEndpointPtr dummy_endpoint;
|
|
|
};
|
|
|
|
|
|
+class Sqlite3QueryBenchMark : public QueryBenchMark {
|
|
|
+public:
|
|
|
+ Sqlite3QueryBenchMark(const int cache_slots,
|
|
|
+ const char* const datasrc_file,
|
|
|
+ const BenchQueries& queries,
|
|
|
+ MessagePtr query_message,
|
|
|
+ OutputBufferPtr buffer) :
|
|
|
+ QueryBenchMark(cache_slots >= 0 ? true : false, queries,
|
|
|
+ query_message, buffer)
|
|
|
+ {
|
|
|
+ if (cache_slots >= 0) {
|
|
|
+ server_->setCacheSlots(cache_slots);
|
|
|
+ }
|
|
|
+ server_->updateConfig(Element::fromJSON("{\"database_file\": \"" +
|
|
|
+ string(datasrc_file) + "\"}"));
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+class MemoryQueryBenchMark : public QueryBenchMark {
|
|
|
+public:
|
|
|
+ MemoryQueryBenchMark(const char* const zone_file,
|
|
|
+ const char* const zone_origin,
|
|
|
+ const BenchQueries& queries,
|
|
|
+ MessagePtr query_message,
|
|
|
+ OutputBufferPtr buffer) :
|
|
|
+ QueryBenchMark(false, queries, query_message, buffer)
|
|
|
+ {
|
|
|
+ configureAuthServer(*server_,
|
|
|
+ Element::fromJSON(
|
|
|
+ "{\"datasources\": "
|
|
|
+ " [{\"type\": \"memory\","
|
|
|
+ " \"zones\": [{\"origin\": \"" +
|
|
|
+ string(zone_origin) + "\","
|
|
|
+ " \"file\": \"" +
|
|
|
+ string(zone_file) + "\"}]}]}"));
|
|
|
+ }
|
|
|
+};
|
|
|
+
|
|
|
+void
|
|
|
+printQPSResult(unsigned int iteration, double duration,
|
|
|
+ double iteration_per_second)
|
|
|
+{
|
|
|
+ cout.precision(6);
|
|
|
+ cout << "Processed " << iteration << " queries in "
|
|
|
+ << fixed << duration << "s";
|
|
|
+ cout.precision(2);
|
|
|
+ cout << " (" << fixed << iteration_per_second << "qps)" << endl;
|
|
|
+}
|
|
|
}
|
|
|
|
|
|
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;
|
|
|
+BenchMark<Sqlite3QueryBenchMark>::printResult() const {
|
|
|
+ printQPSResult(getIteration(), getDuration(), getIterationPerSecond());
|
|
|
+}
|
|
|
+
|
|
|
+template<>
|
|
|
+void
|
|
|
+BenchMark<MemoryQueryBenchMark>::printResult() const {
|
|
|
+ printQPSResult(getIteration(), getDuration(), getIterationPerSecond());
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
namespace {
|
|
|
+const int ITERATION_DEFAULT = 1;
|
|
|
+enum DataSrcType {
|
|
|
+ SQLITE3,
|
|
|
+ MEMORY
|
|
|
+};
|
|
|
+
|
|
|
void
|
|
|
usage() {
|
|
|
- cerr << "Usage: query_bench [-n iterations] datasrc_file query_datafile"
|
|
|
+ cerr <<
|
|
|
+ "Usage: query_bench [-n iterations] [-t datasrc_type] [-o origin] "
|
|
|
+ "datasrc_file query_datafile\n"
|
|
|
+ " -n Number of iterations per test case (default: "
|
|
|
+ << ITERATION_DEFAULT << ")\n"
|
|
|
+ " -t Type of data source: sqlite3|memory (default: sqlite3)\n"
|
|
|
+ " -o Origin name of datasrc_file necessary for \"memory\", "
|
|
|
+ "ignored for others\n"
|
|
|
+ " datasrc_file: sqlite3 DB file for \"sqlite3\", "
|
|
|
+ "textual master file for \"memory\" datasrc\n"
|
|
|
+ " query_datafile: queryperf style input data"
|
|
|
<< endl;
|
|
|
exit (1);
|
|
|
}
|
|
@@ -136,12 +201,20 @@ usage() {
|
|
|
int
|
|
|
main(int argc, char* argv[]) {
|
|
|
int ch;
|
|
|
- int iteration = 1;
|
|
|
- while ((ch = getopt(argc, argv, "n:")) != -1) {
|
|
|
+ int iteration = ITERATION_DEFAULT;
|
|
|
+ const char* opt_datasrc_type = "sqlite3";
|
|
|
+ const char* origin = NULL;
|
|
|
+ while ((ch = getopt(argc, argv, "n:t:o:")) != -1) {
|
|
|
switch (ch) {
|
|
|
case 'n':
|
|
|
iteration = atoi(optarg);
|
|
|
break;
|
|
|
+ case 't':
|
|
|
+ opt_datasrc_type = optarg;
|
|
|
+ break;
|
|
|
+ case 'o':
|
|
|
+ origin = optarg;
|
|
|
+ break;
|
|
|
case '?':
|
|
|
default:
|
|
|
usage();
|
|
@@ -155,6 +228,21 @@ main(int argc, char* argv[]) {
|
|
|
const char* const datasrc_file = argv[0];
|
|
|
const char* const query_data_file = argv[1];
|
|
|
|
|
|
+ DataSrcType datasrc_type = SQLITE3;
|
|
|
+ if (strcmp(opt_datasrc_type, "sqlite3") == 0) {
|
|
|
+ ; // no need to override
|
|
|
+ } else if (strcmp(opt_datasrc_type, "memory") == 0) {
|
|
|
+ datasrc_type = MEMORY;
|
|
|
+ } else {
|
|
|
+ cerr << "Unknown data source type: " << datasrc_type << endl;
|
|
|
+ return (1);
|
|
|
+ }
|
|
|
+
|
|
|
+ if (datasrc_type == MEMORY && origin == NULL) {
|
|
|
+ cerr << "'-o Origin' is missing for memory data source " << endl;
|
|
|
+ return (1);
|
|
|
+ }
|
|
|
+
|
|
|
BenchQueries queries;
|
|
|
loadQueryData(query_data_file, queries, RRClass::IN());
|
|
|
OutputBufferPtr buffer(new OutputBuffer(4096));
|
|
@@ -162,32 +250,46 @@ main(int argc, char* argv[]) {
|
|
|
|
|
|
cout << "Parameters:" << endl;
|
|
|
cout << " Iterations: " << iteration << endl;
|
|
|
- cout << " Data Source: " << datasrc_file << endl;
|
|
|
+ cout << " Data Source: type=" << opt_datasrc_type << ", file=" <<
|
|
|
+ datasrc_file << endl;
|
|
|
+ if (origin != NULL) {
|
|
|
+ cout << " Origin: " << origin << endl;
|
|
|
+ }
|
|
|
cout << " Query data: file=" << query_data_file << " (" << queries.size()
|
|
|
<< " queries)" << endl << endl;
|
|
|
|
|
|
- cout << "Benchmark enabling Hot Spot Cache with unlimited slots "
|
|
|
- << endl;
|
|
|
- BenchMark<QueryBenchMark>(iteration,
|
|
|
- QueryBenchMark(0, datasrc_file, queries, message,
|
|
|
- buffer));
|
|
|
+ switch (datasrc_type) {
|
|
|
+ case SQLITE3:
|
|
|
+ cout << "Benchmark enabling Hot Spot Cache with unlimited slots "
|
|
|
+ << endl;
|
|
|
+ BenchMark<Sqlite3QueryBenchMark>(
|
|
|
+ iteration, Sqlite3QueryBenchMark(0, datasrc_file, queries,
|
|
|
+ message, buffer));
|
|
|
|
|
|
- cout << "Benchmark enabling Hot Spot Cache with 10*#queries slots "
|
|
|
- << endl;
|
|
|
- BenchMark<QueryBenchMark>(iteration,
|
|
|
- QueryBenchMark(10 * queries.size(), datasrc_file,
|
|
|
+ cout << "Benchmark enabling Hot Spot Cache with 10*#queries slots "
|
|
|
+ << endl;
|
|
|
+ BenchMark<Sqlite3QueryBenchMark>(
|
|
|
+ iteration, Sqlite3QueryBenchMark(10 * queries.size(), datasrc_file,
|
|
|
queries, message, buffer));
|
|
|
|
|
|
- cout << "Benchmark enabling Hot Spot Cache with #queries/2 slots "
|
|
|
- << endl;
|
|
|
- BenchMark<QueryBenchMark>(iteration,
|
|
|
- QueryBenchMark(queries.size() / 2, datasrc_file,
|
|
|
+ cout << "Benchmark enabling Hot Spot Cache with #queries/2 slots "
|
|
|
+ << endl;
|
|
|
+ BenchMark<Sqlite3QueryBenchMark>(
|
|
|
+ iteration, Sqlite3QueryBenchMark(queries.size() / 2, datasrc_file,
|
|
|
queries, message, buffer));
|
|
|
|
|
|
- cout << "Benchmark disabling Hot Spot Cache" << endl;
|
|
|
- BenchMark<QueryBenchMark>(iteration,
|
|
|
- QueryBenchMark(-1, datasrc_file, queries,
|
|
|
- message, buffer));
|
|
|
+ cout << "Benchmark disabling Hot Spot Cache" << endl;
|
|
|
+ BenchMark<Sqlite3QueryBenchMark>(
|
|
|
+ iteration, Sqlite3QueryBenchMark(-1, datasrc_file, queries,
|
|
|
+ message, buffer));
|
|
|
+ break;
|
|
|
+ case MEMORY:
|
|
|
+ cout << "Benchmark with In Memory Data Source" << endl;
|
|
|
+ BenchMark<MemoryQueryBenchMark>(
|
|
|
+ iteration, MemoryQueryBenchMark(datasrc_file, origin, queries,
|
|
|
+ message, buffer));
|
|
|
+ break;
|
|
|
+ }
|
|
|
|
|
|
return (0);
|
|
|
}
|