mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 16:57:35 +00:00
Kernel: Cache Custody objects (weakly) to avoid expensive reconstruction
This patch adds a (spinlock-protected) custody cache. It's a simple intrusive list containing all currently live custody objects. This allows us to re-use existing custodies instead of creating them again and again. This gives a pretty decent performance improvement on "find /" :^)
This commit is contained in:
parent
a412fd2ed8
commit
d6d7d11590
2 changed files with 52 additions and 8 deletions
|
@ -4,23 +4,59 @@
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <AK/Singleton.h>
|
||||||
#include <AK/StringBuilder.h>
|
#include <AK/StringBuilder.h>
|
||||||
#include <AK/StringView.h>
|
#include <AK/StringView.h>
|
||||||
#include <AK/Vector.h>
|
#include <AK/Vector.h>
|
||||||
#include <Kernel/FileSystem/Custody.h>
|
#include <Kernel/FileSystem/Custody.h>
|
||||||
#include <Kernel/FileSystem/Inode.h>
|
#include <Kernel/FileSystem/Inode.h>
|
||||||
|
#include <Kernel/Locking/SpinLockProtectedValue.h>
|
||||||
|
|
||||||
namespace Kernel {
|
namespace Kernel {
|
||||||
|
|
||||||
|
static Singleton<SpinLockProtectedValue<Custody::AllCustodiesList>> s_all_custodies;
|
||||||
|
|
||||||
|
static SpinLockProtectedValue<Custody::AllCustodiesList>& all_custodies()
|
||||||
|
{
|
||||||
|
return s_all_custodies;
|
||||||
|
}
|
||||||
|
|
||||||
KResultOr<NonnullRefPtr<Custody>> Custody::try_create(Custody* parent, StringView name, Inode& inode, int mount_flags)
|
KResultOr<NonnullRefPtr<Custody>> Custody::try_create(Custody* parent, StringView name, Inode& inode, int mount_flags)
|
||||||
{
|
{
|
||||||
auto name_kstring = KString::try_create(name);
|
return all_custodies().with([&](auto& all_custodies) -> KResultOr<NonnullRefPtr<Custody>> {
|
||||||
if (!name_kstring)
|
for (Custody& custody : all_custodies) {
|
||||||
return ENOMEM;
|
if (custody.parent() == parent
|
||||||
auto custody = adopt_ref_if_nonnull(new (nothrow) Custody(parent, name_kstring.release_nonnull(), inode, mount_flags));
|
&& custody.name() == name
|
||||||
if (!custody)
|
&& &custody.inode() == &inode
|
||||||
return ENOMEM;
|
&& custody.mount_flags() == mount_flags) {
|
||||||
return custody.release_nonnull();
|
return custody;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto name_kstring = KString::try_create(name);
|
||||||
|
if (!name_kstring)
|
||||||
|
return ENOMEM;
|
||||||
|
auto custody = adopt_ref_if_nonnull(new (nothrow) Custody(parent, name_kstring.release_nonnull(), inode, mount_flags));
|
||||||
|
if (!custody)
|
||||||
|
return ENOMEM;
|
||||||
|
|
||||||
|
all_custodies.append(*custody);
|
||||||
|
return custody.release_nonnull();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Custody::unref() const
|
||||||
|
{
|
||||||
|
bool should_destroy = all_custodies().with([&](auto&) {
|
||||||
|
if (deref_base())
|
||||||
|
return false;
|
||||||
|
m_all_custodies_list_node.remove();
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (should_destroy)
|
||||||
|
delete this;
|
||||||
|
return should_destroy;
|
||||||
}
|
}
|
||||||
|
|
||||||
Custody::Custody(Custody* parent, NonnullOwnPtr<KString> name, Inode& inode, int mount_flags)
|
Custody::Custody(Custody* parent, NonnullOwnPtr<KString> name, Inode& inode, int mount_flags)
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <AK/IntrusiveList.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
@ -18,9 +19,11 @@ namespace Kernel {
|
||||||
|
|
||||||
// FIXME: Custody needs some locking.
|
// FIXME: Custody needs some locking.
|
||||||
|
|
||||||
class Custody : public RefCounted<Custody> {
|
class Custody : public RefCountedBase {
|
||||||
MAKE_SLAB_ALLOCATED(Custody)
|
MAKE_SLAB_ALLOCATED(Custody)
|
||||||
public:
|
public:
|
||||||
|
bool unref() const;
|
||||||
|
|
||||||
static KResultOr<NonnullRefPtr<Custody>> try_create(Custody* parent, StringView name, Inode&, int mount_flags);
|
static KResultOr<NonnullRefPtr<Custody>> try_create(Custody* parent, StringView name, Inode&, int mount_flags);
|
||||||
|
|
||||||
~Custody();
|
~Custody();
|
||||||
|
@ -43,6 +46,11 @@ private:
|
||||||
NonnullOwnPtr<KString> m_name;
|
NonnullOwnPtr<KString> m_name;
|
||||||
NonnullRefPtr<Inode> m_inode;
|
NonnullRefPtr<Inode> m_inode;
|
||||||
int m_mount_flags { 0 };
|
int m_mount_flags { 0 };
|
||||||
|
|
||||||
|
mutable IntrusiveListNode<Custody> m_all_custodies_list_node;
|
||||||
|
|
||||||
|
public:
|
||||||
|
using AllCustodiesList = IntrusiveList<Custody, RawPtr<Custody>, &Custody::m_all_custodies_list_node>;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue