From 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sat, 27 Apr 2024 20:24:20 +0200 Subject: Adding upstream version 14.2.21. Signed-off-by: Daniel Baumann --- .../objectstore/ObjectStoreTransactionBenchmark.cc | 269 +++++++++++++++++++++ 1 file changed, 269 insertions(+) create mode 100644 src/test/objectstore/ObjectStoreTransactionBenchmark.cc (limited to 'src/test/objectstore/ObjectStoreTransactionBenchmark.cc') diff --git a/src/test/objectstore/ObjectStoreTransactionBenchmark.cc b/src/test/objectstore/ObjectStoreTransactionBenchmark.cc new file mode 100644 index 00000000..5e248cbe --- /dev/null +++ b/src/test/objectstore/ObjectStoreTransactionBenchmark.cc @@ -0,0 +1,269 @@ +// -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- +// vim: ts=8 sw=2 smarttab +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2014 UnitedStack + * + * Author: Haomai Wang + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ + +#include +#include +#include +#include + +using namespace std; + +#include "common/ceph_argparse.h" +#include "common/debug.h" +#include "common/Cycles.h" +#include "global/global_init.h" +#include "os/ObjectStore.h" + +class Transaction { + private: + ObjectStore::Transaction t; + + public: + struct Tick { + uint64_t ticks; + uint64_t count; + Tick(): ticks(0), count(0) {} + void add(uint64_t a) { + ticks += a; + count++; + } + }; + static Tick write_ticks, setattr_ticks, omap_setkeys_ticks, omap_rmkeys_ticks; + static Tick encode_ticks, decode_ticks, iterate_ticks; + + void write(coll_t cid, const ghobject_t& oid, uint64_t off, uint64_t len, + const bufferlist& data) { + uint64_t start_time = Cycles::rdtsc(); + t.write(cid, oid, off, len, data); + write_ticks.add(Cycles::rdtsc() - start_time); + } + void setattr(coll_t cid, const ghobject_t& oid, const string &name, + bufferlist& val) { + uint64_t start_time = Cycles::rdtsc(); + t.setattr(cid, oid, name, val); + setattr_ticks.add(Cycles::rdtsc() - start_time); + } + void omap_setkeys(coll_t cid, const ghobject_t &oid, + const map &attrset) { + + uint64_t start_time = Cycles::rdtsc(); + t.omap_setkeys(cid, oid, attrset); + omap_setkeys_ticks.add(Cycles::rdtsc() - start_time); + } + void omap_rmkeys(coll_t cid, const ghobject_t &oid, + const set &keys) { + uint64_t start_time = Cycles::rdtsc(); + t.omap_rmkeys(cid, oid, keys); + omap_rmkeys_ticks.add(Cycles::rdtsc() - start_time); + } + + void apply_encode_decode() { + bufferlist bl; + ObjectStore::Transaction d; + uint64_t start_time = Cycles::rdtsc(); + t.encode(bl); + encode_ticks.add(Cycles::rdtsc() - start_time); + + auto bliter = bl.cbegin(); + start_time = Cycles::rdtsc(); + d.decode(bliter); + decode_ticks.add(Cycles::rdtsc() - start_time); + } + + void apply_iterate() { + uint64_t start_time = Cycles::rdtsc(); + ObjectStore::Transaction::iterator i = t.begin(); + while (i.have_op()) { + ObjectStore::Transaction::Op *op = i.decode_op(); + + switch (op->op) { + case ObjectStore::Transaction::OP_WRITE: + { + ghobject_t oid = i.get_oid(op->oid); + bufferlist bl; + i.decode_bl(bl); + } + break; + case ObjectStore::Transaction::OP_SETATTR: + { + ghobject_t oid = i.get_oid(op->oid); + string name = i.decode_string(); + bufferlist bl; + i.decode_bl(bl); + map to_set; + to_set[name] = bufferptr(bl.c_str(), bl.length()); + } + break; + case ObjectStore::Transaction::OP_OMAP_SETKEYS: + { + ghobject_t oid = i.get_oid(op->oid); + map aset; + i.decode_attrset(aset); + } + break; + case ObjectStore::Transaction::OP_OMAP_RMKEYS: + { + ghobject_t oid = i.get_oid(op->oid); + set keys; + i.decode_keyset(keys); + } + break; + } + } + iterate_ticks.add(Cycles::rdtsc() - start_time); + } + + static void dump_stat() { + cerr << " write op: " << Cycles::to_microseconds(write_ticks.ticks) << "us count: " << write_ticks.count << std::endl; + cerr << " setattr op: " << Cycles::to_microseconds(setattr_ticks.ticks) << "us count: " << setattr_ticks.count << std::endl; + cerr << " omap_setkeys op: " << Cycles::to_microseconds(Transaction::omap_setkeys_ticks.ticks) << "us count: " << Transaction::omap_setkeys_ticks.count << std::endl; + cerr << " omap_rmkeys op: " << Cycles::to_microseconds(Transaction::omap_rmkeys_ticks.ticks) << "us count: " << Transaction::omap_rmkeys_ticks.count << std::endl; + cerr << " encode op: " << Cycles::to_microseconds(Transaction::encode_ticks.ticks) << "us count: " << Transaction::encode_ticks.count << std::endl; + cerr << " decode op: " << Cycles::to_microseconds(Transaction::decode_ticks.ticks) << "us count: " << Transaction::decode_ticks.count << std::endl; + cerr << " iterate op: " << Cycles::to_microseconds(Transaction::iterate_ticks.ticks) << "us count: " << Transaction::iterate_ticks.count << std::endl; + } +}; + +class PerfCase { + static const uint64_t Kib = 1024; + static const uint64_t Mib = 1024 * 1024; + static const string info_epoch_attr; + static const string info_info_attr; + static const string attr; + static const string snapset_attr; + static const string pglog_attr; + static const coll_t meta_cid; + static const coll_t cid; + static const ghobject_t pglog_oid; + static const ghobject_t info_oid; + map data; + + ghobject_t create_object() { + bufferlist bl = generate_random(100, 1); + return ghobject_t(hobject_t(string("obj_")+string(bl.c_str()), string(), rand() & 2 ? CEPH_NOSNAP : rand(), rand() & 0xFF, 0, "")); + } + + + bufferlist generate_random(uint64_t len, int frag) { + static const char alphanum[] = "0123456789" + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz"; + uint64_t per_frag = len / frag; + bufferlist bl; + for (int i = 0; i < frag; i++ ) { + bufferptr bp(per_frag); + for (unsigned int j = 0; j < len; j++) { + bp[j] = alphanum[rand() % (sizeof(alphanum) - 1)]; + } + bl.append(bp); + } + return bl; + } + public: + PerfCase() { + uint64_t four_kb = Kib * 4; + uint64_t one_mb = Mib * 1; + uint64_t four_mb = Mib * 4; + data["4k"] = generate_random(four_kb, 1); + data["1m"] = generate_random(one_mb, 1); + data["4m"] = generate_random(four_mb, 1); + data[attr] = generate_random(256, 1); + data[snapset_attr] = generate_random(32, 1); + data[pglog_attr] = generate_random(128, 1); + data[info_epoch_attr] = generate_random(4, 1); + data[info_info_attr] = generate_random(560, 1); + } + + uint64_t rados_write_4k(int times) { + uint64_t ticks = 0; + uint64_t len = Kib *4; + for (int i = 0; i < times; i++) { + uint64_t start_time = 0; + { + Transaction t; + ghobject_t oid = create_object(); + start_time = Cycles::rdtsc(); + t.write(cid, oid, 0, len, data["4k"]); + t.setattr(cid, oid, attr, data[attr]); + t.setattr(cid, oid, snapset_attr, data[snapset_attr]); + t.apply_encode_decode(); + t.apply_iterate(); + ticks += Cycles::rdtsc() - start_time; + } + { + Transaction t; + map pglog_attrset; + map info_attrset; + set keys; + keys.insert(pglog_attr); + pglog_attrset[pglog_attr] = data[pglog_attr]; + info_attrset[info_epoch_attr] = data[info_epoch_attr]; + info_attrset[info_info_attr] = data[info_info_attr]; + start_time = Cycles::rdtsc(); + t.omap_setkeys(meta_cid, pglog_oid, pglog_attrset); + t.omap_setkeys(meta_cid, info_oid, info_attrset); + t.omap_rmkeys(meta_cid, pglog_oid, keys); + t.apply_encode_decode(); + t.apply_iterate(); + ticks += Cycles::rdtsc() - start_time; + } + } + return ticks; + } +}; +const string PerfCase::info_epoch_attr("11.40_epoch"); +const string PerfCase::info_info_attr("11.40_info"); +const string PerfCase::attr("_"); +const string PerfCase::snapset_attr("snapset"); +const string PerfCase::pglog_attr("pglog_attr"); +const coll_t PerfCase::meta_cid; +const coll_t PerfCase::cid; +const ghobject_t PerfCase::pglog_oid(hobject_t(sobject_t(object_t("cid_pglog"), 0))); +const ghobject_t PerfCase::info_oid(hobject_t(sobject_t(object_t("infos"), 0))); +Transaction::Tick Transaction::write_ticks, Transaction::setattr_ticks, Transaction::omap_setkeys_ticks, Transaction::omap_rmkeys_ticks; +Transaction::Tick Transaction::encode_ticks, Transaction::decode_ticks, Transaction::iterate_ticks; + +void usage(const string &name) { + cerr << "Usage: " << name << " [times] " + << std::endl; +} + +int main(int argc, char **argv) +{ + vector args; + argv_to_vec(argc, (const char **)argv, args); + + auto cct = global_init(NULL, args, CEPH_ENTITY_TYPE_CLIENT, + CODE_ENVIRONMENT_UTILITY, + CINIT_FLAG_NO_DEFAULT_CONFIG_FILE); + common_init_finish(g_ceph_context); + g_ceph_context->_conf.apply_changes(nullptr); + Cycles::init(); + + cerr << "args: " << args << std::endl; + if (args.size() < 1) { + usage(argv[0]); + return 1; + } + + uint64_t times = atoi(args[0]); + PerfCase c; + uint64_t ticks = c.rados_write_4k(times); + Transaction::dump_stat(); + cerr << " Total rados op " << times << " run time " << Cycles::to_microseconds(ticks) << "us." << std::endl; + + return 0; +} -- cgit v1.2.3