A dirns class that is an array of xns instances.

An xns must fit in a page, but that doesn't allow enough buckets to avoid physical sharing in dirbench. This is basically a work-around for the one page limit.
上级 cb7ca72d
......@@ -2,26 +2,76 @@
u64 namehash(const strbuf<DIRSIZ>&);
#define NINS 251
// Prevent potentially non-scalable bucket groupings
static_assert(NINS != NHASH, "Bad NINS choice");
class dirns : public rcu_freed
{
typedef xns<strbuf<DIRSIZ>, u32, namehash> ins;
public:
dirns() : rcu_freed("dirns"), ns_(false) {}
dirns() : rcu_freed("dirns") {
for (int i = 0; i < NINS; i++)
a_[i].store(nullptr);
}
~dirns() {
for (int i = 0; i < NINS; i++)
if (a_[i].load() != nullptr) {
delete a_[i].load();
a_[i].store(nullptr);
}
}
bool remove(const strbuf<DIRSIZ>& name, const u32* vp = nullptr) {
return ns_.remove(name, vp);
u32 i = ah(name);
if (a_[i].load() != nullptr)
return a_[i].load()->remove(name, vp);
return false;
}
int insert(const strbuf<DIRSIZ>& name, const u32& inum) {
return ns_.insert(name, inum);
ins* ns;
u32 i;
i = ah(name);
retry:
if (a_[i].load() == nullptr) {
ns = new ins(false);
if (!cmpxch(&a_[i], (decltype(ns)) nullptr, ns)) {
delete ns;
goto retry;
}
} else {
ns = a_[i];
}
return ns->insert(name, inum);
}
u32 lookup(const strbuf<DIRSIZ>& name) {
return ns_.lookup(name);
u32 lookup(const strbuf<DIRSIZ>& name) const {
ins* ns;
u32 i;
i = ah(name);
ns = a_[i].load();
if (ns != nullptr)
return ns->lookup(name);
return 0;
}
template<class CB>
void enumerate(CB cb) {
return ns_.enumerate(cb);
void enumerate(CB cb) const {
// XXX(sbw) not the same semantics as xns::enumerate.
// This continues if cb returns true.
for (int i = 0; i < NINS; i++) {
ins* ns = a_[i].load();
if (ns != nullptr)
ns->enumerate(cb);
}
}
virtual void do_gc(void) {
......@@ -31,5 +81,10 @@ public:
NEW_DELETE_OPS(dirns);
private:
xns<strbuf<DIRSIZ>, u32, namehash> ns_;
std::atomic<ins*> a_[NINS];
u32 ah(const strbuf<DIRSIZ>& name) const {
u64 h = namehash(name);
return h % NINS;
}
};
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论