| // 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/pseudo_dir.h> |
| #include <fs/pseudo_file.h> |
| #include <perftest/perftest.h> |
| |
| #include "src/lib/fxl/strings/string_printf.h" |
| #include "util.h" |
| |
| namespace { |
| |
| // Benchmark baseline creation time. |
| bool PseudoDirCreateTest(perftest::RepeatState* state) { |
| while (state->KeepRunning()) { |
| perftest::DoNotOptimize(fs::PseudoDir()); |
| } |
| return true; |
| } |
| |
| // Benchmark the time to remove an existing entry and add it back. |
| // Parameterized by the number of files. |
| bool PseudoDirRemoveAddTest(perftest::RepeatState* state, int file_count) { |
| auto file_names = util::MakeDeterministicNamesList(file_count); |
| |
| auto dir = fbl::AdoptRef(new fs::PseudoDir()); |
| auto file = fbl::AdoptRef(new fs::UnbufferedPseudoFile()); |
| |
| for (const auto& name : file_names) { |
| dir->AddEntry(name, file); |
| } |
| |
| int i = 0; |
| |
| while (state->KeepRunning()) { |
| dir->RemoveEntry(file_names[i]); |
| dir->AddEntry(file_names[i], file); |
| i = (i + 1) % file_names.size(); |
| } |
| return true; |
| } |
| |
| // Benchmark the time to lookup an existing entry. |
| // Parameterized by the number of files. |
| bool PseudoDirLookupTest(perftest::RepeatState* state, int file_count) { |
| auto file_names = util::MakeDeterministicNamesList(file_count); |
| |
| auto dir = fbl::AdoptRef(new fs::PseudoDir()); |
| auto file = fbl::AdoptRef(new fs::UnbufferedPseudoFile()); |
| |
| for (const auto& name : file_names) { |
| dir->AddEntry(name, file); |
| } |
| |
| int i = 0; |
| fbl::RefPtr<fs::Vnode> out; |
| |
| while (state->KeepRunning()) { |
| dir->Lookup(file_names[i], &out); |
| i = (i + 1) % file_names.size(); |
| } |
| return true; |
| } |
| |
| // Benchmark the time to read out a directory. |
| // Parameterized by the number of files and the size of the output buffer. |
| bool PseudoDirReaddirTest(perftest::RepeatState* state, int file_count, int buffer_size) { |
| auto file_names = util::MakeDeterministicNamesList(file_count); |
| std::vector<char> buffer(buffer_size); |
| |
| auto dir = fbl::AdoptRef(new fs::PseudoDir()); |
| auto file = fbl::AdoptRef(new fs::UnbufferedPseudoFile()); |
| |
| for (const auto& name : file_names) { |
| dir->AddEntry(name, file); |
| } |
| |
| fs::VdirCookie cookie; |
| while (state->KeepRunning()) { |
| size_t real_len = 0; |
| do { |
| auto status = dir->Readdir(&cookie, buffer.data(), buffer.size(), &real_len); |
| ZX_DEBUG_ASSERT(ZX_OK == status); |
| } while (real_len > 0); |
| } |
| return true; |
| } |
| |
| void RegisterTests() { |
| perftest::RegisterTest("PseudoDir/Create", PseudoDirCreateTest); |
| |
| for (int file_count = 1; file_count <= 1 << 14; file_count *= 8) { |
| auto name = fbl::StringPrintf("PseudoDir/RemoveAdd/%d", file_count); |
| perftest::RegisterTest(name.c_str(), PseudoDirRemoveAddTest, file_count); |
| } |
| |
| for (int file_count = 1; file_count <= 1 << 14; file_count *= 8) { |
| auto name = fbl::StringPrintf("PseudoDir/Lookup/%d", file_count); |
| perftest::RegisterTest(name.c_str(), PseudoDirLookupTest, file_count); |
| } |
| |
| for (int buffer_size = 1; buffer_size <= 64; buffer_size *= 8) { |
| for (int file_count = 1; file_count <= 1 << 14; file_count *= 8) { |
| auto name = fbl::StringPrintf("PseudoDir/Readdir/%d/%dk", file_count, buffer_size); |
| perftest::RegisterTest(name.c_str(), PseudoDirReaddirTest, file_count, buffer_size * 1024); |
| } |
| } |
| } |
| |
| PERFTEST_CTOR(RegisterTests); |
| |
| } // namespace |