packagefs: Use object caches for the most used node classes.

Slab statistics from KDL show that on a stock nightly image
(i.e. no additional packages besides the standards installed)
there are 43848 *objects* (not bytes) in the PackageNodeAttribute
cache, and 25090 in the PackageFile cache, so this seems more than
worth it.

The last commit seems to reduce memory usage at boot by about 1%,
this commit seems to not affect it at all; but it is a significant
performance optimization and on systems with more packages installed
the effect may be very noticeable.

Change-Id: I676a642ed6003f82b14396e1f02684575d899362
This commit is contained in:
Augustin Cavalier 2019-07-09 00:54:53 -04:00
parent 71e255cd31
commit d230b5fdd3
8 changed files with 64 additions and 3 deletions

View File

@ -140,7 +140,7 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
PackageNode* node;
if (S_ISREG(mode)) {
// file
node = new(std::nothrow) PackageFile(fPackage, mode,
node = new PackageFile(fPackage, mode,
PackageData(entry->Data()));
} else if (S_ISLNK(mode)) {
// symlink
@ -157,7 +157,7 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
node = symlink;
} else if (S_ISDIR(mode)) {
// directory
node = new(std::nothrow) PackageDirectory(fPackage, mode);
node = new PackageDirectory(fPackage, mode);
} else
RETURN_ERROR(B_BAD_DATA);
@ -201,7 +201,7 @@ struct Package::LoaderContentHandler : BPackageContentHandler {
if (!name.SetTo(attribute->Name()))
RETURN_ERROR(B_NO_MEMORY);
PackageNodeAttribute* nodeAttribute = new(std::nothrow)
PackageNodeAttribute* nodeAttribute = new
PackageNodeAttribute(attribute->Type(),
PackageData(attribute->Data()));
if (nodeAttribute == NULL)

View File

@ -7,6 +7,11 @@
#include "PackageDirectory.h"
#include "Package.h"
#include "ClassCache.h"
CLASS_CACHE(PackageDirectory);
PackageDirectory::PackageDirectory(Package* package, mode_t mode)
:

View File

@ -14,6 +14,9 @@
class PackageDirectory : public PackageNode,
public DoublyLinkedListLinkImpl<PackageDirectory> {
public:
static void* operator new(size_t size);
static void operator delete(void* block);
PackageDirectory(Package* package, mode_t mode);
virtual ~PackageDirectory();

View File

@ -19,12 +19,19 @@
#include <util/AutoLock.h>
#include "DebugSupport.h"
#include "ClassCache.h"
#include "Package.h"
using namespace BPackageKit::BHPKG;
// #pragma mark - class cache
CLASS_CACHE(PackageFile);
// #pragma mark - DataAccessor

View File

@ -12,6 +12,9 @@
class PackageFile : public PackageLeafNode {
public:
static void* operator new(size_t size);
static void operator delete(void* block);
PackageFile(Package* package, mode_t mode,
const PackageData& data);
virtual ~PackageFile();

View File

@ -9,6 +9,11 @@
#include <stdlib.h>
#include <string.h>
#include "ClassCache.h"
CLASS_CACHE(PackageNodeAttribute);
PackageNodeAttribute::PackageNodeAttribute(uint32 type,
const PackageData& data)

View File

@ -19,6 +19,9 @@ class PackageNode;
class PackageNodeAttribute
: public DoublyLinkedListLinkImpl<PackageNodeAttribute> {
public:
static void* operator new(size_t size);
static void operator delete(void* block);
PackageNodeAttribute(uint32 type,
const PackageData& data);
~PackageNodeAttribute();

View File

@ -0,0 +1,35 @@
/*
* Copyright 2019, Haiku, Inc. All rights reserved.
* Distributed under the terms of the MIT License.
*/
#ifndef CLASSCACHE_H
#define CLASSCACHE_H
#include <slab/Slab.h>
#define CLASS_CACHE(CLASS) \
static object_cache* s##CLASS##Cache = NULL; \
\
void* \
CLASS::operator new(size_t size) \
{ \
if (size != sizeof(CLASS)) \
panic("unexpected size passed to operator new!"); \
if (s##CLASS##Cache == NULL) { \
s##CLASS##Cache = create_object_cache("packagefs " #CLASS "s", \
sizeof(CLASS), 8, NULL, NULL, NULL); \
} \
\
return object_cache_alloc(s##CLASS##Cache, 0); \
} \
\
void \
CLASS::operator delete(void* block) \
{ \
object_cache_free(s##CLASS##Cache, block, 0); \
}
#endif // CLASSCACHE_H