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 @@ ...@@ -2,26 +2,76 @@
u64 namehash(const strbuf<DIRSIZ>&); 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 class dirns : public rcu_freed
{ {
typedef xns<strbuf<DIRSIZ>, u32, namehash> ins;
public: 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) { 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) { 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) { u32 lookup(const strbuf<DIRSIZ>& name) const {
return ns_.lookup(name); ins* ns;
u32 i;
i = ah(name);
ns = a_[i].load();
if (ns != nullptr)
return ns->lookup(name);
return 0;
} }
template<class CB> template<class CB>
void enumerate(CB cb) { void enumerate(CB cb) const {
return ns_.enumerate(cb); // 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) { virtual void do_gc(void) {
...@@ -31,5 +81,10 @@ public: ...@@ -31,5 +81,10 @@ public:
NEW_DELETE_OPS(dirns); NEW_DELETE_OPS(dirns);
private: 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 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论