/************************************************************************ * EOS - the CERN Disk Storage System * * Copyright (C) 2016 CERN/Switzerland * * * * This program is free software: you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation, either version 3 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * * along with this program. If not, see .* ************************************************************************/ #include "XrdOuc/XrdOucString.hh" #include "XrdSys/XrdSysPthread.hh" #include "common/LinuxStat.hh" #include "common/LinuxMemConsumption.hh" #include "common/RWMutex.hh" #include "common/StringConversion.hh" #include "common/Timing.hh" #include "namespace/ns_quarkdb/persistency/ContainerMDSvc.hh" #include "namespace/ns_quarkdb/persistency/FileMDSvc.hh" #include "namespace/ns_quarkdb/views/HierarchicalView.hh" #include #include #include #include #include eos::common::RWMutex nslock; #if 0 //------------------------------------------------------------------------------ // File size mapping function //------------------------------------------------------------------------------ static uint64_t mapSize(const eos::IFileMD* /*file*/) { return 0u; } //------------------------------------------------------------------------------ // Boot the namespace //------------------------------------------------------------------------------ eos::IView* bootNamespace(const std::map& config) { eos::IContainerMDSvc* contSvc = new eos::QuarkContainerMDSvc(); eos::IFileMDSvc* fileSvc = new eos::QuarkFileMDSvc(); eos::IView* view = new eos::QuarkHierarchicalView(); fileSvc->configure(config); contSvc->configure(config); fileSvc->setContMDService(contSvc); contSvc->setFileMDService(fileSvc); view->setContainerMDSvc(contSvc); view->setFileMDSvc(fileSvc); view->configure(config); view->getQuotaStats()->registerSizeMapper(mapSize); view->initialize(); return view; } //------------------------------------------------------------------------------ // Close the namespace //------------------------------------------------------------------------------ void closeNamespace(eos::IView* view) { eos::IContainerMDSvc* contSvc = view->getContainerMDSvc(); eos::IFileMDSvc* fileSvc = view->getFileMDSvc(); view->finalize(); delete view; delete contSvc; delete fileSvc; } //------------------------------------------------------------------------------ // Print current namespace status //------------------------------------------------------------------------------ void PrintStatus(eos::IView* view, eos::common::LinuxStat::linux_stat_t* st1, eos::common::LinuxStat::linux_stat_t* st2, eos::common::LinuxMemConsumption::linux_mem_t* /*mem1*/, eos::common::LinuxMemConsumption::linux_mem_t* mem2, const double& rate, bool print_total = false) { XrdOucString sizestring; XrdOucString stdOut; eos::IContainerMDSvc* contSvc = view->getContainerMDSvc(); eos::IFileMDSvc* fileSvc = view->getFileMDSvc(); unsigned long long f = 0, d = 0; if (print_total) { f = static_cast(fileSvc->getNumFiles()); d = static_cast(contSvc->getNumContainers()); } char files[256]; snprintf(static_cast(files), sizeof(files) - 1, "%llu", f); char dirs[256]; snprintf(static_cast(dirs), sizeof(dirs) - 1, "%llu", d); stdOut += "# -------------------------------------------------------------\n"; stdOut += "ALL Files "; stdOut += static_cast(files); stdOut += "\n"; stdOut += "ALL Directories "; stdOut += static_cast(dirs); stdOut += "\n"; stdOut += "# -------------------------------------------------------------\n"; stdOut += "ALL memory virtual "; stdOut += eos::common::StringConversion::GetReadableSizeString( sizestring, mem2->vmsize, "B"); stdOut += "\n"; stdOut += "ALL memory resident "; stdOut += eos::common::StringConversion::GetReadableSizeString( sizestring, mem2->resident, "B"); stdOut += "\n"; stdOut += "ALL memory share "; stdOut += eos::common::StringConversion::GetReadableSizeString( sizestring, mem2->share, "B"); stdOut += "\n"; stdOut += "ALL memory growths "; stdOut += eos::common::StringConversion::GetReadableSizeString( sizestring, (st2->vsize - st1->vsize), "B"); stdOut += "\n"; stdOut += "# -------------------------------------------------------------\n"; stdOut += "ALL rate "; char srate[256]; snprintf(static_cast(srate), sizeof(srate) - 1, "%.02f", rate); stdOut += static_cast(srate); stdOut += "\n"; stdOut += "# -------------------------------------------------------------\n"; fprintf(stderr, "%s", stdOut.c_str()); } class RThread { public: RThread() = default; ~RThread() = default; RThread(size_t a, size_t b, size_t c, size_t d, eos::IView* iview, bool lock = false) { i = a; n_j = b; n_k = c; n_files = d; view = iview; dolock = lock; } size_t i; size_t n_j; size_t n_k; size_t n_files; bool dolock; eos::IView* view; }; //---------------------------------------------------------------------------- // Start namespace consumer thread //---------------------------------------------------------------------------- static void* RunReader(void* tconf) { RThread* r = static_cast(tconf); size_t i = r->i; size_t n_j = r->n_j; size_t n_k = r->n_k; size_t n_files = r->n_files; eos::IView* view = r->view; bool dolock = r->dolock; try { for (size_t j = 0; j < n_j; j++) { for (size_t k = 0; k < n_k; k++) { for (size_t n = 0; n < n_files; n++) { char s_file_path[1024]; snprintf(static_cast(s_file_path), sizeof(s_file_path) - 1, "/eos/nsbench/level_0_%08u/" "level_1_%08u/level_2_%08u/file____________________%08u", static_cast(i), static_cast(j), static_cast(k), static_cast(n)); std::string file_path = static_cast(s_file_path); if (dolock) { nslock.LockRead(); } std::shared_ptr fmd = view->getFile(file_path); if (fmd) { unsigned long long size = fmd->getSize(); (void) size; } if (dolock) { nslock.UnLockRead(); } } } } } catch (eos::MDException& e) { std::cerr << "[!] Error: " << e.getMessage().str() << std::endl; } return nullptr; } //------------------------------------------------------------------------------ // Main function //---------------------------------------------------------------------------- int main(int argc, char** argv) { // Check up the commandline params if (argc != 5) { std::cerr << "Usage:" << std::endl; std::cerr << " eos-namespace-benchmark " << " " << std::endl; return 1; } std::map config = {{"qdb_host", argv[1]}, {"qdb_port", argv[2]} }; size_t n_i = std::stoi(argv[3]); size_t n_j = 64; size_t n_k = 64; size_t n_files = std::stoi(argv[4]); // Create Namespace and populate dirs try { std::cerr << "# ***********************************************************" << std::endl; std::cerr << "[i] Initialize Directory Namespace..." << std::endl; std::cerr << "# ***********************************************************" << std::endl; eos::IView* view = bootNamespace(config); eos::common::LinuxStat::linux_stat_t st[10]; ; eos::common::LinuxMemConsumption::linux_mem_t mem[10]; eos::common::LinuxStat::GetStat(st[0]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[0]); eos::common::Timing tm("directories"); COMMONTIMING("dir-start", &tm); for (size_t i = 0; i < n_i; i++) { fprintf(stderr, "# Level %02u\n", static_cast(i)); XrdOucString l = "dir-level-"; l += static_cast(i); COMMONTIMING(l.c_str(), &tm); for (size_t j = 0; j < n_j; j++) { for (size_t k = 0; k < n_k; k++) { char s_container_path[1024]; snprintf(static_cast(s_container_path), sizeof(s_container_path) - 1, "/eos/nsbench/level_0_%08u/level_1_%08u/level_2_%08u/", static_cast(i), static_cast(j), static_cast(k)); std::string container_path = static_cast(s_container_path); std::shared_ptr cont = view->createContainer(container_path, true); cont->setAttribute("sys.forced.blocksize", "4k"); cont->setAttribute("sys.forced.checksum", "adler"); cont->setAttribute("sys.forced.layout", "replica"); cont->setAttribute("sys.forced.nstripes", "2"); cont->setAttribute("user.acl", "u:atlas003:rw,egroup:atlas-comp-cern-storage-support:rw"); view->updateContainerStore(cont.get()); } } } eos::common::LinuxStat::GetStat(st[1]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[1]); COMMONTIMING("dir-stop", &tm); tm.Print(); double rate = (n_i * n_j * n_k) / tm.RealTime() * 1000.0; PrintStatus(view, &st[0], &st[1], &mem[0], &mem[1], rate); closeNamespace(view); } catch (eos::MDException& e) { std::cerr << "[!] Error: " << e.getMessage().str() << std::endl; return 2; } // Fill namespace with files try { std::cerr << "# ***********************************************************" << std::endl; std::cerr << "[i] Initialize File Namespace ..." << std::endl; std::cerr << "# ***********************************************************" << std::endl; eos::IView* view = bootNamespace(config); eos::common::LinuxStat::linux_stat_t st[10]; ; eos::common::LinuxMemConsumption::linux_mem_t mem[10]; eos::common::LinuxStat::GetStat(st[0]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[0]); eos::common::Timing tm("files"); COMMONTIMING("dir-start", &tm); for (size_t i = 0; i < n_i; i++) { fprintf(stderr, "# Level %02u\n", static_cast(i)); XrdOucString l = "dir-level-"; l += static_cast(i); COMMONTIMING(l.c_str(), &tm); for (size_t j = 0; j < n_j; j++) { for (size_t k = 0; k < n_k; k++) { for (size_t n = 0; n < n_files; n++) { char s_file_path[1024]; snprintf(static_cast(s_file_path), sizeof(s_file_path) - 1, "/eos/nsbench/level_0_%08u/" "level_1_%08u/level_2_%08u/file____________________%08u", static_cast(i), static_cast(j), static_cast(k), static_cast(n)); std::string file_path = static_cast(s_file_path); std::shared_ptr fmd = view->createFile(file_path, 0, 0); // add two locations fmd->addLocation(k); fmd->addLocation(k + 1); // fmd->addLocation(k+2); // fmd->addLocation(k+3); // fmd->addLocation(k+4); // fmd->addLocation(k+5); fmd->setLayoutId(10); view->updateFileStore(fmd.get()); } } } } eos::common::LinuxStat::GetStat(st[1]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[1]); COMMONTIMING("dir-stop", &tm); tm.Print(); double rate = (n_files * n_i * n_j * n_k) / tm.RealTime() * 1000.0; PrintStatus(view, &st[0], &st[1], &mem[0], &mem[1], rate); closeNamespace(view); } catch (eos::MDException& e) { std::cerr << "[!] Error: " << e.getMessage().str() << std::endl; return 2; } eos::IView* view = nullptr; // Run a parallel consumer thread benchmark without locking { eos::common::LinuxStat::linux_stat_t st[10]; ; eos::common::LinuxMemConsumption::linux_mem_t mem[10]; std::cerr << "# ***********************************************************" << std::endl; std::cerr << "[i] Parallel reader benchmark without locking ..." << std::endl; std::cerr << "# ***********************************************************" << std::endl; view = bootNamespace(config); eos::common::LinuxStat::GetStat(st[0]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[0]); eos::common::Timing tm("reading"); COMMONTIMING("read-start", &tm); pthread_t tid[1024]; // fire threads for (size_t i = 0; i < n_i; i++) { fprintf(stderr, "# Level %02u\n", static_cast(i)); RThread r(i, n_j, n_k, n_files, view); XrdSysThread::Run(&tid[i], RunReader, static_cast(&r), XRDSYSTHREAD_HOLD, "Reader Thread"); } // join them for (size_t i = 0; i < n_i; i++) { XrdSysThread::Join(tid[i], nullptr); } eos::common::LinuxStat::GetStat(st[1]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[1]); COMMONTIMING("read-stop", &tm); tm.Print(); double rate = (n_files * n_i * n_j * n_k) / tm.RealTime() * 1000.0; PrintStatus(view, &st[0], &st[1], &mem[0], &mem[1], rate); } // Run a parallel consumer thread benchmark with namespace locking { eos::common::LinuxStat::linux_stat_t st[10]; ; eos::common::LinuxMemConsumption::linux_mem_t mem[10]; std::cerr << "# ***********************************************************" << std::endl; std::cerr << "[i] Parallel reader benchmark with locking ..." << std::endl; std::cerr << "# ***********************************************************" << std::endl; eos::common::LinuxStat::GetStat(st[0]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[0]); eos::common::Timing tm("reading"); COMMONTIMING("read-lock-start", &tm); pthread_t tid[1024]; // fire threads for (size_t i = 0; i < n_i; i++) { fprintf(stderr, "# Level %02u\n", static_cast(i)); RThread r(i, n_j, n_k, n_files, view, true); XrdSysThread::Run(&tid[i], RunReader, static_cast(&r), XRDSYSTHREAD_HOLD, "Reader Thread"); } // join them for (size_t i = 0; i < n_i; i++) { XrdSysThread::Join(tid[i], nullptr); } eos::common::LinuxStat::GetStat(st[1]); eos::common::LinuxMemConsumption::GetMemoryFootprint(mem[1]); COMMONTIMING("read-lock-stop", &tm); tm.Print(); double rate = (n_files * n_i * n_j * n_k) / tm.RealTime() * 1000.0; PrintStatus(view, &st[0], &st[1], &mem[0], &mem[1], rate); } return 0; } #endif int main() { return 0; }