| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <zircon/syscalls.h> |
| |
| #include <random> |
| #include <vector> |
| |
| #include <fbl/ref_ptr.h> |
| #include <fbl/string_printf.h> |
| #include <fs/lazy_dir.h> |
| #include <fs/vfs.h> |
| #include <perftest/perftest.h> |
| |
| #include "assert.h" |
| #include "src/lib/fxl/strings/string_printf.h" |
| #include "util.h" |
| |
| namespace { |
| |
| class TestLazyDir : public fs::LazyDir { |
| public: |
| void AddEntry(LazyEntry entry) { entries_.push_back(std::move(entry)); } |
| |
| protected: |
| void GetContents(LazyEntryVector* out_vector) override { |
| out_vector->reserve(entries_.size()); |
| for (const auto& entry : entries_) { |
| out_vector->push_back(entry); |
| } |
| } |
| |
| zx_status_t GetFile(fbl::RefPtr<Vnode>* out_vnode, uint64_t id, fbl::String name) override { |
| // Do nothing to benchmark obtaining id and name. |
| return ZX_OK; |
| } |
| |
| fbl::Vector<LazyEntry> entries_; |
| }; |
| |
| // Measure the time taken to create an empty LazyDir. |
| bool TestCreate(perftest::RepeatState* state) { |
| while (state->KeepRunning()) { |
| ZX_ASSERT(fbl::AdoptRef<TestLazyDir>(new TestLazyDir()) != nullptr); |
| } |
| return true; |
| } |
| |
| // Measure the time taken to look up an entry in a LazyDir of a given size. |
| bool TestLookup(perftest::RepeatState* state, size_t file_count) { |
| auto file_names = util::MakeDeterministicNamesList(file_count); |
| |
| auto dir = fbl::AdoptRef(new TestLazyDir()); |
| |
| uint64_t id = 1; |
| for (const auto& name : file_names) { |
| dir->AddEntry({id++, name, V_TYPE_FILE}); |
| } |
| |
| int i = 0; |
| while (state->KeepRunning()) { |
| fbl::RefPtr<fs::Vnode> out; |
| ASSERT_OK(dir->Lookup(file_names[i], &out)); |
| i = (i + 1) % file_names.size(); |
| } |
| return true; |
| } |
| |
| // Measure the time taken to read directory entries from a LazyDir of |
| // a given size using a given sized buffer. |
| bool TestReaddir(perftest::RepeatState* state, size_t file_count, size_t buffer_size) { |
| auto file_names = util::MakeDeterministicNamesList(file_count); |
| std::vector<char> buffer(buffer_size); |
| |
| auto dir = fbl::AdoptRef(new TestLazyDir()); |
| |
| uint64_t id = 1; |
| for (const auto& name : file_names) { |
| dir->AddEntry({id++, name, V_TYPE_FILE}); |
| } |
| |
| fs::VdirCookie cookie; |
| while (state->KeepRunning()) { |
| size_t real_len = 0; |
| while (dir->Readdir(&cookie, buffer.data(), buffer_size, &real_len) != ZX_OK) { |
| ZX_ASSERT(real_len != 0); |
| } |
| } |
| return true; |
| } |
| |
| void RegisterTests() { |
| static const size_t kSizes[] = {1, 8, 64, 512, 4 * 1024, 16 * 1024}; |
| static const size_t kBuffers[] = {1024, 4 * 1024, 16 * 1024, 64 * 1024}; |
| perftest::RegisterTest("LazyDir/Create", TestCreate); |
| for (auto size : kSizes) { |
| auto name = fbl::StringPrintf("LazyDir/Lookup/size:%zd", size); |
| perftest::RegisterTest(name.c_str(), TestLookup, size); |
| } |
| |
| for (auto size : kSizes) { |
| for (auto buffer : kBuffers) { |
| auto name = fbl::StringPrintf("LazyDir/Readdir/size:%zd/buf:%zd", size, buffer); |
| perftest::RegisterTest(name.c_str(), TestReaddir, size, buffer); |
| } |
| } |
| } |
| PERFTEST_CTOR(RegisterTests); |
| |
| } // namespace |