Skip to content

Commit

Permalink
KPath: Use an object_cache for the path buffers in the normal case.
Browse files Browse the repository at this point in the history
This was (following the packagefs changes) the number-one (by call
count) consumer of malloc() during the boot -- 52866 calls, and 100%
of them either 1024 or 1025 bytes!

Virtually all of these are ephemeral (indeed, the object_cache
stats after a boot with this patch shows there is only a single slab
of 64 buffers allocated, and most of them unused), so this is
probably a significant performance boost.

Change-Id: I659f5707510cbfeafa735d35eea7b92732ead666
  • Loading branch information
waddlesplash committed Jul 12, 2019
1 parent 9b72c3a commit 42e3c6f
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 60 deletions.
7 changes: 4 additions & 3 deletions headers/private/kernel/fs/KPath.h
Expand Up @@ -23,14 +23,14 @@ class KPath {
LAZY_ALLOC = 0x04
};
public:
KPath(size_t bufferSize = B_PATH_NAME_LENGTH);
KPath(size_t bufferSize = B_PATH_NAME_LENGTH + 1);
KPath(const char* path, int32 flags = DEFAULT,
size_t bufferSize = B_PATH_NAME_LENGTH);
size_t bufferSize = B_PATH_NAME_LENGTH + 1);
KPath(const KPath& other);
~KPath();

status_t SetTo(const char* path, int32 flags = DEFAULT,
size_t bufferSize = B_PATH_NAME_LENGTH);
size_t bufferSize = B_PATH_NAME_LENGTH + 1);
void Adopt(KPath& other);

status_t InitCheck() const;
Expand Down Expand Up @@ -67,6 +67,7 @@ class KPath {

private:
status_t _AllocateBuffer();
void _FreeBuffer();
status_t _Normalize(const char* path,
bool traverseLeafLink);
void _ChopTrailingSlashes();
Expand Down
Expand Up @@ -197,7 +197,7 @@ class KDiskDeviceManager::DeviceWatcher : public NotificationListener {

if (strcmp(event->name, "raw") == 0) {
// a new raw device was added/removed
KPath path(B_PATH_NAME_LENGTH + 1);
KPath path;
if (path.InitCheck() != B_OK
|| vfs_entry_ref_to_path(event->device, event->directory,
event->name, true, path.LockBuffer(),
Expand Down
48 changes: 40 additions & 8 deletions src/system/kernel/fs/KPath.cpp
Expand Up @@ -15,13 +15,19 @@

#include <team.h>
#include <vfs.h>
#include <slab/Slab.h>


// debugging
#define TRACE(x) ;
//#define TRACE(x) dprintf x


#ifdef _KERNEL_MODE
extern object_cache* sPathNameCache;
#endif


KPath::KPath(size_t bufferSize)
:
fBuffer(NULL),
Expand Down Expand Up @@ -66,20 +72,19 @@ KPath::KPath(const KPath& other)

KPath::~KPath()
{
free(fBuffer);
_FreeBuffer();
}


status_t
KPath::SetTo(const char* path, int32 flags, size_t bufferSize)
{
if (bufferSize == 0)
bufferSize = B_PATH_NAME_LENGTH;
bufferSize = B_PATH_NAME_LENGTH + 1;

// free the previous buffer, if the buffer size differs
if (fBuffer != NULL && fBufferSize != bufferSize) {
free(fBuffer);
fBuffer = NULL;
_FreeBuffer();
fBufferSize = 0;
}

Expand All @@ -102,7 +107,7 @@ KPath::SetTo(const char* path, int32 flags, size_t bufferSize)
void
KPath::Adopt(KPath& other)
{
free(fBuffer);
_FreeBuffer();

fBuffer = other.fBuffer;
fBufferSize = other.fBufferSize;
Expand Down Expand Up @@ -218,7 +223,9 @@ void
KPath::UnlockBuffer()
{
if (!fLocked) {
TRACE(("KPath::UnlockBuffer(): ERROR: Buffer not locked!\n"));
#ifdef _KERNEL_MODE
panic("KPath::UnlockBuffer(): Buffer not locked!");
#endif
return;
}

Expand All @@ -242,6 +249,12 @@ KPath::DetachBuffer()
{
char* buffer = fBuffer;

if (fBufferSize == (B_PATH_NAME_LENGTH + 1)) {
buffer = (char*)malloc(fBufferSize);
memcpy(buffer, fBuffer, fBufferSize);
_FreeBuffer();
}

if (fBuffer != NULL) {
fBuffer = NULL;
fPathLength = 0;
Expand Down Expand Up @@ -412,8 +425,14 @@ KPath::operator!=(const char* path) const
status_t
KPath::_AllocateBuffer()
{
if (fBuffer == NULL && fBufferSize != 0)
fBuffer = (char*)malloc(fBufferSize);
if (fBuffer == NULL && fBufferSize != 0) {
#ifdef _KERNEL_MODE
if (fBufferSize == (B_PATH_NAME_LENGTH + 1))
fBuffer = (char*)object_cache_alloc(sPathNameCache, 0);
else
#endif
fBuffer = (char*)malloc(fBufferSize);
}
if (fBuffer == NULL) {
fFailed = true;
return B_NO_MEMORY;
Expand All @@ -425,6 +444,19 @@ KPath::_AllocateBuffer()
}


void
KPath::_FreeBuffer()
{
#ifdef _KERNEL_MODE
if (fBufferSize == (B_PATH_NAME_LENGTH + 1))
object_cache_free(sPathNameCache, fBuffer, 0);
else
#endif
free(fBuffer);
fBuffer = NULL;
}


status_t
KPath::_Normalize(const char* path, bool traverseLeafLink)
{
Expand Down

0 comments on commit 42e3c6f

Please sign in to comment.