Browse Source

copy from the experimental branch

git-svn-id: svn://bind10.isc.org/svn/bind10/branches/trac241@2140 e5f2f494-b856-4b98-b285-d166d9295462
JINMEI Tatuya 15 years ago
parent
commit
d586dfbc28
2 changed files with 242 additions and 0 deletions
  1. 7 0
      src/lib/dns/benchmarks/Makefile.am
  2. 235 0
      src/lib/dns/benchmarks/buffer_bench.cc

+ 7 - 0
src/lib/dns/benchmarks/Makefile.am

@@ -0,0 +1,7 @@
+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

+ 235 - 0
src/lib/dns/benchmarks/buffer_bench.cc

@@ -0,0 +1,235 @@
+// 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);
+}