query_bench.cc 9.58 KB
Newer Older
JINMEI Tatuya's avatar
JINMEI Tatuya committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// 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.

15 16
#include <config.h>

JINMEI Tatuya's avatar
JINMEI Tatuya committed
17 18 19 20 21 22 23 24 25 26
#include <stdlib.h>

#include <iostream>
#include <vector>

#include <boost/shared_ptr.hpp>

#include <bench/benchmark.h>
#include <bench/benchmark_util.h>

27
#include <util/buffer.h>
JINMEI Tatuya's avatar
JINMEI Tatuya committed
28 29 30 31 32 33 34 35
#include <dns/message.h>
#include <dns/name.h>
#include <dns/question.h>
#include <dns/rrclass.h>

#include <xfr/xfrout_client.h>

#include <auth/auth_srv.h>
36
#include <auth/auth_config.h>
37
#include <auth/query.h>
Jerry's avatar
Jerry committed
38

39
#include <asiodns/asiodns.h>
Michal Vaner's avatar
Michal Vaner committed
40
#include <asiolink/asiolink.h>
JINMEI Tatuya's avatar
JINMEI Tatuya committed
41 42 43

using namespace std;
using namespace isc;
44
using namespace isc::data;
45
using namespace isc::auth;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
46
using namespace isc::dns;
47
using namespace isc::util;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
48 49
using namespace isc::xfr;
using namespace isc::bench;
50 51
using namespace isc::asiodns;
using namespace isc::asiolink;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
52 53 54 55 56

namespace {
// Commonly used constant:
XfroutClient xfrout_client("dummy_path"); // path doesn't matter

Michal Vaner's avatar
Michal Vaner committed
57 58 59
// Just something to pass as the server to resume
class DummyServer : public DNSServer {
    public:
60 61
        virtual void operator()(asio::error_code, size_t) {}
        virtual void resume(const bool) {}
Michal Vaner's avatar
Michal Vaner committed
62
        virtual DNSServer* clone() {
63
            return (new DummyServer(*this));
Michal Vaner's avatar
Michal Vaner committed
64 65 66
        }
};

JINMEI Tatuya's avatar
JINMEI Tatuya committed
67
class QueryBenchMark {
68
protected:
JINMEI Tatuya's avatar
JINMEI Tatuya committed
69 70 71
    // Maintain dynamically generated objects via shared pointers because
    // QueryBenchMark objects will be copied.
    typedef boost::shared_ptr<AuthSrv> AuthSrvPtr;
72
private:
JINMEI Tatuya's avatar
JINMEI Tatuya committed
73
    typedef boost::shared_ptr<const IOEndpoint> IOEndpointPtr;
74 75
protected:
    QueryBenchMark(const bool enable_cache,
Michal Vaner's avatar
Michal Vaner committed
76 77
                   const BenchQueries& queries, MessagePtr query_message,
                   OutputBufferPtr buffer) :
78
        server_(new AuthSrv(enable_cache, xfrout_client)),
JINMEI Tatuya's avatar
JINMEI Tatuya committed
79 80
        queries_(queries),
        query_message_(query_message),
Michal Vaner's avatar
Michal Vaner committed
81
        buffer_(buffer),
JINMEI Tatuya's avatar
JINMEI Tatuya committed
82 83 84
        dummy_socket(IOSocket::getDummyUDPSocket()),
        dummy_endpoint(IOEndpointPtr(IOEndpoint::create(IPPROTO_UDP,
                                                        IOAddress("192.0.2.1"),
85
                                                        53210)))
86 87
    {}
public:
JINMEI Tatuya's avatar
JINMEI Tatuya committed
88 89 90
    unsigned int run() {
        BenchQueries::const_iterator query;
        const BenchQueries::const_iterator query_end = queries_.end();
Michal Vaner's avatar
Michal Vaner committed
91
        DummyServer server;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
92 93 94
        for (query = queries_.begin(); query != query_end; ++query) {
            IOMessage io_message(&(*query)[0], (*query).size(), dummy_socket,
                                 *dummy_endpoint);
Michal Vaner's avatar
Michal Vaner committed
95
            query_message_->clear(Message::PARSE);
96
            buffer_->clear();
Michal Vaner's avatar
Michal Vaner committed
97
            server_->processMessage(io_message, query_message_, buffer_,
98
                                    &server);
JINMEI Tatuya's avatar
JINMEI Tatuya committed
99 100 101 102
        }

        return (queries_.size());
    }
103
protected:
JINMEI Tatuya's avatar
JINMEI Tatuya committed
104
    AuthSrvPtr server_;
105
private:
JINMEI Tatuya's avatar
JINMEI Tatuya committed
106
    const BenchQueries& queries_;
Michal Vaner's avatar
Michal Vaner committed
107 108
    MessagePtr query_message_;
    OutputBufferPtr buffer_;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
109 110 111
    IOSocket& dummy_socket;
    IOEndpointPtr dummy_endpoint;
};
Michal Vaner's avatar
Michal Vaner committed
112

113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
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;
}
JINMEI Tatuya's avatar
JINMEI Tatuya committed
161 162 163 164 165 166
}

namespace isc {
namespace bench {
template<>
void
167 168 169 170 171 172 173 174
BenchMark<Sqlite3QueryBenchMark>::printResult() const {
    printQPSResult(getIteration(), getDuration(), getIterationPerSecond());
}

template<>
void
BenchMark<MemoryQueryBenchMark>::printResult() const {
    printQPSResult(getIteration(), getDuration(), getIterationPerSecond());
JINMEI Tatuya's avatar
JINMEI Tatuya committed
175 176 177 178 179
}
}
}

namespace {
180 181 182 183 184 185
const int ITERATION_DEFAULT = 1;
enum DataSrcType {
    SQLITE3,
    MEMORY
};

JINMEI Tatuya's avatar
JINMEI Tatuya committed
186 187
void
usage() {
188 189 190 191 192 193 194 195 196 197 198
    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"
JINMEI Tatuya's avatar
JINMEI Tatuya committed
199 200 201 202 203 204 205 206
         << endl;
    exit (1);
}
}

int
main(int argc, char* argv[]) {
    int ch;
207 208 209 210
    int iteration = ITERATION_DEFAULT;
    const char* opt_datasrc_type = "sqlite3";
    const char* origin = NULL;
    while ((ch = getopt(argc, argv, "n:t:o:")) != -1) {
JINMEI Tatuya's avatar
JINMEI Tatuya committed
211 212 213 214
        switch (ch) {
        case 'n':
            iteration = atoi(optarg);
            break;
215 216 217 218 219 220
        case 't':
            opt_datasrc_type = optarg;
            break;
        case 'o':
            origin = optarg;
            break;
JINMEI Tatuya's avatar
JINMEI Tatuya committed
221 222 223 224 225 226 227 228 229 230 231 232 233
        case '?':
        default:
            usage();
        }
    }
    argc -= optind;
    argv += optind;
    if (argc < 2) {
        usage();
    }
    const char* const datasrc_file = argv[0];
    const char* const query_data_file = argv[1];

234 235 236 237 238 239 240 241 242 243 244 245 246 247 248
    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);
    }

JINMEI Tatuya's avatar
JINMEI Tatuya committed
249 250
    BenchQueries queries;
    loadQueryData(query_data_file, queries, RRClass::IN());
Michal Vaner's avatar
Michal Vaner committed
251 252
    OutputBufferPtr buffer(new OutputBuffer(4096));
    MessagePtr message(new Message(Message::PARSE));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
253 254 255

    cout << "Parameters:" << endl;
    cout << "  Iterations: " << iteration << endl;
256 257 258 259 260
    cout << "  Data Source: type=" << opt_datasrc_type << ", file=" <<
        datasrc_file << endl;
    if (origin != NULL) {
        cout << "  Origin: " << origin << endl;
    }
JINMEI Tatuya's avatar
JINMEI Tatuya committed
261 262 263
    cout << "  Query data: file=" << query_data_file << " (" << queries.size()
         << " queries)" << endl << endl;

264 265 266 267 268 269 270
    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));
271

272 273 274 275
        cout << "Benchmark enabling Hot Spot Cache with 10*#queries slots "
             << endl;
        BenchMark<Sqlite3QueryBenchMark>(
            iteration, Sqlite3QueryBenchMark(10 * queries.size(), datasrc_file,
Michal Vaner's avatar
Michal Vaner committed
276
                                             queries, message, buffer));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
277

278 279 280 281
        cout << "Benchmark enabling Hot Spot Cache with #queries/2 slots "
             << endl;
        BenchMark<Sqlite3QueryBenchMark>(
            iteration, Sqlite3QueryBenchMark(queries.size() / 2, datasrc_file,
Michal Vaner's avatar
Michal Vaner committed
282
                                             queries, message, buffer));
JINMEI Tatuya's avatar
JINMEI Tatuya committed
283

284 285 286 287 288 289 290 291 292 293 294 295
        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;
    }
JINMEI Tatuya's avatar
JINMEI Tatuya committed
296 297 298

    return (0);
}