Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
109 changes: 109 additions & 0 deletions cloud/filestore/libs/vfs_fuse/bench/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
#include <cloud/filestore/libs/vfs_fuse/node_cache.h>

#include <library/cpp/testing/benchmark/bench.h>

#include <util/random/fast.h>
#include <util/thread/factory.h>

////////////////////////////////////////////////////////////////////////////////

using namespace NCloud::NFileStore;
using namespace NFuse;

namespace {

////////////////////////////////////////////////////////////////////////////////

void RunBench(ui64 iters, ui32 threads, ui32 shards)
{
TNodeCache cache("fs", shards);
std::atomic<ui64> version = 0;
const ui64 nodeCount = 1'000'000;

struct TContext
{
TManualEvent Ev;
std::atomic<ui32> Todo;
};

auto context = std::make_shared<TContext>();
context->Todo = threads;

for (ui32 i = 0; i < threads; ++i) {
SystemThreadFactory()->Run(
[&cache, &version, iters, threads, context] ()
{
TReallyFastRng32 rng(777);
for (size_t i = 0; i < iters / threads; ++i) {
NProto::TNodeAttr attrs;
attrs.SetId(rng.Uniform(nodeCount));
attrs.SetType(NProto::E_REGULAR_NODE);
cache.UpdateNode(
attrs,
version.fetch_add(1, std::memory_order_release));
}

context->Todo.fetch_sub(1, std::memory_order_release);
context->Ev.Signal();
});
}

while (context->Todo.load(std::memory_order_acquire)) {
context->Ev.WaitI();
context->Ev.Reset();
}
}

} // namespace

////////////////////////////////////////////////////////////////////////////////

Y_CPU_BENCHMARK(UpdateNode1, iface)
{
RunBench(iface.Iterations(), 1, 1);
}

Y_CPU_BENCHMARK(UpdateNode2, iface)
{
RunBench(iface.Iterations(), 2, 1);
}

Y_CPU_BENCHMARK(UpdateNode4, iface)
{
RunBench(iface.Iterations(), 4, 1);
}

Y_CPU_BENCHMARK(UpdateNode8, iface)
{
RunBench(iface.Iterations(), 8, 1);
}

Y_CPU_BENCHMARK(UpdateNode16, iface)
{
RunBench(iface.Iterations(), 16, 1);
}

Y_CPU_BENCHMARK(UpdateNode1_16, iface)
{
RunBench(iface.Iterations(), 1, 16);
}

Y_CPU_BENCHMARK(UpdateNode2_16, iface)
{
RunBench(iface.Iterations(), 2, 16);
}

Y_CPU_BENCHMARK(UpdateNode4_16, iface)
{
RunBench(iface.Iterations(), 4, 16);
}

Y_CPU_BENCHMARK(UpdateNode8_16, iface)
{
RunBench(iface.Iterations(), 8, 16);
}

Y_CPU_BENCHMARK(UpdateNode16_16, iface)
{
RunBench(iface.Iterations(), 16, 16);
}
16 changes: 16 additions & 0 deletions cloud/filestore/libs/vfs_fuse/bench/ya.make
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
Y_BENCHMARK()

IF (SANITIZER_TYPE)
TAG(ya:manual)
ENDIF()

SRCS(
main.cpp
)

PEERDIR(
cloud/filestore/libs/vfs_fuse
cloud/filestore/libs/vfs_fuse/vhost
)

END()
4 changes: 2 additions & 2 deletions cloud/filestore/libs/vfs_fuse/fs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,12 @@ int ReplyAttr(
const NCloud::NProto::TError& error,
fuse_req_t req,
const struct stat *attr,
double attr_timeout)
double attrTimeout)
{
requestStats.ResponseSent(callContext);
FILESTORE_TRACK(ResponseSent, (&callContext), "Attr");

int res = fuse_reply_attr(req, attr, attr_timeout);
int res = fuse_reply_attr(req, attr, attrTimeout);
if (res != 0) {
STORAGE_WARN(callContext.LogString()
<< " fuse_reply_attr failed with code " << res);
Expand Down
112 changes: 112 additions & 0 deletions cloud/filestore/libs/vfs_fuse/fs_directory_content_format.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
#include "fs_directory_content_format.h"

#if defined(FUSE_VIRTIO)
# include<cloud/contrib/virtiofsd/fuse.h>
#endif

#include <util/system/align.h>

namespace NCloud::NFileStore::NFuse {

////////////////////////////////////////////////////////////////////////////////

TDirectoryBuilder::TDirectoryBuilder(size_t size) noexcept
: Buffer(std::make_shared<TBuffer>(size))
{}

void TDirectoryBuilder::Add(
fuse_req_t req,
const TString& name,
const fuse_entry_param& entry,
size_t offset)
{
#if defined(FUSE_VIRTIO)
size_t entrySize = fuse_add_direntry_plus(
req,
nullptr,
0,
name.c_str(),
&entry,
0);

Buffer->Advance(entrySize);

fuse_add_direntry_plus(
req,
Buffer->Pos() - entrySize,
entrySize,
name.c_str(),
&entry,
offset + Buffer->Size());
#else
size_t entrySize = fuse_add_direntry(
req,
nullptr,
0,
name.c_str(),
&entry.attr,
0);

Buffer->Advance(entrySize);

fuse_add_direntry(
req,
Buffer->Pos() - entrySize,
entrySize,
name.c_str(),
&entry.attr,
offset + Buffer->Size());
#endif
}

TBufferPtr TDirectoryBuilder::Finish()
{
return std::move(Buffer);
}

////////////////////////////////////////////////////////////////////////////////

NProto::TError ResetAttrTimeout(
char* data,
ui64 len,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remainingLen

const TNodeIdVisitor& visitor)
{
#if defined(FUSE_VIRTIO)
while (len > sizeof(fuse_direntplus)) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

probably add commit that expect no name with 0 lens

auto* de = reinterpret_cast<fuse_direntplus*>(data);

if (de->dirent.ino != de->entry_out.attr.ino) {
return MakeError(E_INVALID_STATE, TStringBuilder() << "ino mismatch"
<< " in dirent and attr: " << de->dirent.ino << " != "
<< de->entry_out.attr.ino);
}

if (visitor(de->dirent.ino)) {
de->entry_out.attr_valid = 0;
de->entry_out.attr_valid_nsec = 0;
}

const ui64 fullSize = sizeof(fuse_direntplus)
+ AlignUp<ui64>(de->dirent.namelen, sizeof(ui64));

if (len < fullSize) {
return MakeError(E_INVALID_STATE, TStringBuilder() << "expected >= "
<< fullSize << " bytes of dir content, have " << len
<< " bytes");
}

len -= fullSize;
data += fullSize;
}
#else
// for non-virtiofs builds we don't return attrs in listing results

Y_UNUSED(data);
Y_UNUSED(len);
Y_UNUSED(visitor);
#endif

return MakeError(S_OK);
}

} // namespace NCloud::NFileStore::NFuse
34 changes: 34 additions & 0 deletions cloud/filestore/libs/vfs_fuse/fs_directory_content_format.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#pragma once

#include "fs_directory_handle.h"

namespace NCloud::NFileStore::NFuse {

////////////////////////////////////////////////////////////////////////////////

class TDirectoryBuilder
{
private:
TBufferPtr Buffer;

public:
explicit TDirectoryBuilder(size_t size) noexcept;

void Add(
fuse_req_t req,
const TString& name,
const fuse_entry_param& entry,
size_t offset);

TBufferPtr Finish();
};

////////////////////////////////////////////////////////////////////////////////

using TNodeIdVisitor = std::function<bool(ui64)>;
NProto::TError ResetAttrTimeout(
char* data,
ui64 len,
const TNodeIdVisitor& visitor);

} // namespace NCloud::NFileStore::NFuse
Loading
Loading