From: Yan, Zheng Date: Fri, 6 Feb 2015 12:53:49 +0000 (+0800) Subject: mds: optimize memory usage of class InodeStore X-Git-Tag: v9.0.0~201^2~8 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=3075a07902dc96d89aaac35882a9b4848c4924e3;p=ceph.git mds: optimize memory usage of class InodeStore InodeStore::old_inodes and InodeStore::snap_blob are for snapshotted inode only. their size are 48 bytes and 80 bytes respectively. Defining InodeStore::old_inodes can save 40 bytes, allocating bufferlist for snap_blob dynamiclly can save 72 bytes. Signed-off-by: Yan, Zheng --- diff --git a/src/mds/CDir.cc b/src/mds/CDir.cc index 9943add99f1..903b1916c45 100644 --- a/src/mds/CDir.cc +++ b/src/mds/CDir.cc @@ -1707,8 +1707,8 @@ void CDir::_omap_fetched(bufferlist& hdrbl, map& omap, in->dirfragtree.swap(inode_data.dirfragtree); in->xattrs.swap(inode_data.xattrs); in->old_inodes.swap(inode_data.old_inodes); - in->decode_snap_blob(inode_data.snap_blob); in->oldest_snap = inode_data.oldest_snap; + in->decode_snap_blob(inode_data.snap_blob); if (snaps && !in->snaprealm) in->purge_stale_snap_data(*snaps); @@ -2012,9 +2012,9 @@ void CDir::_encode_dentry(CDentry *dn, bufferlist& bl, if (in->is_multiversion() && snaps && !in->snaprealm) in->purge_stale_snap_data(*snaps); - in->encode_snap_blob(in->snap_blob); - in->encode_bare(bl); - in->snap_blob.clear(); + bufferlist snap_blob; + in->encode_snap_blob(snap_blob); + in->encode_bare(bl, &snap_blob); } } diff --git a/src/mds/CInode.cc b/src/mds/CInode.cc index e98c74af08b..cdeb23bb13e 100644 --- a/src/mds/CInode.cc +++ b/src/mds/CInode.cc @@ -926,7 +926,7 @@ struct C_IO_Inode_Stored : public CInodeIOContext { } }; -object_t InodeStore::get_object_name(inodeno_t ino, frag_t fg, const char *suffix) +object_t InodeStoreBase::get_object_name(inodeno_t ino, frag_t fg, const char *suffix) { char n[60]; snprintf(n, sizeof(n), "%llx.%08llx%s", (long long unsigned)ino, (long long unsigned)fg, suffix ? suffix : ""); @@ -1240,33 +1240,37 @@ void CInode::verify_diri_backtrace(bufferlist &bl, int err) // parent dir -void InodeStore::encode_bare(bufferlist &bl) const +void InodeStoreBase::encode_bare(bufferlist &bl, const bufferlist *snap_blob) const { ::encode(inode, bl); if (is_symlink()) ::encode(symlink, bl); ::encode(dirfragtree, bl); ::encode(xattrs, bl); - ::encode(snap_blob, bl); + if (snap_blob) + ::encode(*snap_blob, bl); + else + ::encode(bufferlist(), bl); ::encode(old_inodes, bl); ::encode(oldest_snap, bl); } -void InodeStore::encode(bufferlist &bl) const +void InodeStoreBase::encode(bufferlist &bl, const bufferlist *snap_blob) const { ENCODE_START(5, 4, bl); - encode_bare(bl); + encode_bare(bl, snap_blob); ENCODE_FINISH(bl); } void CInode::encode_store(bufferlist& bl) { + bufferlist snap_blob; encode_snap_blob(snap_blob); - InodeStore::encode(bl); - snap_blob.clear(); + InodeStoreBase::encode(bl, &snap_blob); } -void InodeStore::decode_bare(bufferlist::iterator &bl, __u8 struct_v) +void InodeStoreBase::decode_bare(bufferlist::iterator &bl, + bufferlist& snap_blob, __u8 struct_v) { ::decode(inode, bl); if (is_symlink()) @@ -1274,6 +1278,7 @@ void InodeStore::decode_bare(bufferlist::iterator &bl, __u8 struct_v) ::decode(dirfragtree, bl); ::decode(xattrs, bl); ::decode(snap_blob, bl); + ::decode(old_inodes, bl); if (struct_v == 2 && inode.is_dir()) { bool default_layout_exists; @@ -1288,18 +1293,18 @@ void InodeStore::decode_bare(bufferlist::iterator &bl, __u8 struct_v) } -void InodeStore::decode(bufferlist::iterator &bl) +void InodeStoreBase::decode(bufferlist::iterator &bl, bufferlist& snap_blob) { DECODE_START_LEGACY_COMPAT_LEN(5, 4, 4, bl); - decode_bare(bl, struct_v); + decode_bare(bl, snap_blob, struct_v); DECODE_FINISH(bl); } void CInode::decode_store(bufferlist::iterator& bl) { - InodeStore::decode(bl); + bufferlist snap_blob; + InodeStoreBase::decode(bl, snap_blob); decode_snap_blob(snap_blob); - snap_blob.clear(); } // ------------------ @@ -2424,7 +2429,7 @@ old_inode_t& CInode::cow_old_inode(snapid_t follows, bool cow_head) void CInode::split_old_inode(snapid_t snap) { - map::iterator p = old_inodes.lower_bound(snap); + compact_map::iterator p = old_inodes.lower_bound(snap); assert(p != old_inodes.end() && p->second.first < snap); old_inode_t &old = old_inodes[snap - 1]; @@ -2449,7 +2454,7 @@ void CInode::purge_stale_snap_data(const set& snaps) if (old_inodes.empty()) return; - map::iterator p = old_inodes.begin(); + compact_map::iterator p = old_inodes.begin(); while (p != old_inodes.end()) { set::const_iterator q = snaps.lower_bound(p->second.first); if (q == snaps.end() || *q > p->first) { @@ -2465,7 +2470,7 @@ void CInode::purge_stale_snap_data(const set& snaps) */ old_inode_t * CInode::pick_old_inode(snapid_t snap) { - map::iterator p = old_inodes.lower_bound(snap); // p is first key >= to snap + compact_map::iterator p = old_inodes.lower_bound(snap); // p is first key >= to snap if (p != old_inodes.end() && p->second.first <= snap) { dout(10) << "pick_old_inode snap " << snap << " -> [" << p->second.first << "," << p->first << "]" << dendl; return &p->second; @@ -2979,7 +2984,7 @@ int CInode::encode_inodestat(bufferlist& bl, Session *session, if (!is_auth()) valid = false; - map::iterator p = old_inodes.lower_bound(snapid); + compact_map::iterator p = old_inodes.lower_bound(snapid); if (p != old_inodes.end()) { if (p->second.first > snapid) { if (p != old_inodes.begin()) @@ -3538,7 +3543,9 @@ void InodeStore::dump(Formatter *f) const // FIXME: dirfragtree: dump methods for fragtree_t // FIXME: xattrs: JSON-safe versions of binary xattrs f->open_array_section("old_inodes"); - for (std::map::const_iterator i = old_inodes.begin(); i != old_inodes.end(); ++i) { + for (compact_map::const_iterator i = old_inodes.begin(); + i != old_inodes.end(); + ++i) { f->open_object_section("old_inode"); { // The key is the last snapid, the first is in the old_inode_t diff --git a/src/mds/CInode.h b/src/mds/CInode.h index f73144bc1c3..aff95e9bffb 100644 --- a/src/mds/CInode.h +++ b/src/mds/CInode.h @@ -70,18 +70,16 @@ extern int num_cinode_locks; * handle CInodes from the backing store without hitting all * the business logic in CInode proper. */ -class InodeStore { +class InodeStoreBase { public: inode_t inode; // the inode itself std::string symlink; // symlink dest, if symlink std::map xattrs; fragtree_t dirfragtree; // dir frag tree, if any. always consistent with our dirfrag map. - std::map old_inodes; // key = last, value.first = first - bufferlist snap_blob; // Encoded copy of SnapRealm, because we can't - // rehydrate it without full MDCache + compact_map old_inodes; // key = last, value.first = first snapid_t oldest_snap; - InodeStore() : oldest_snap(CEPH_NOSNAP) { } + InodeStoreBase() : oldest_snap(CEPH_NOSNAP) { } /* Helpers */ bool is_file() const { return inode.is_file(); } @@ -90,20 +88,37 @@ public: static object_t get_object_name(inodeno_t ino, frag_t fg, const char *suffix); /* Full serialization for use in ".inode" root inode objects */ - void encode(bufferlist &bl) const; - void decode(bufferlist::iterator &bl); + void encode(bufferlist &bl, const bufferlist *snap_blob=NULL) const; + void decode(bufferlist::iterator &bl, bufferlist& snap_blob); /* Serialization without ENCODE_START/FINISH blocks for use embedded in dentry */ - void encode_bare(bufferlist &bl) const; - void decode_bare(bufferlist::iterator &bl, __u8 struct_v=5); + void encode_bare(bufferlist &bl, const bufferlist *snap_blob=NULL) const; + void decode_bare(bufferlist::iterator &bl, bufferlist &snap_blob, __u8 struct_v=5); +}; +class InodeStore : public InodeStoreBase { +public: + bufferlist snap_blob; // Encoded copy of SnapRealm, because we can't + // rehydrate it without full MDCache + void encode(bufferlist &bl) const { + InodeStoreBase::encode(bl, &snap_blob); + } + void decode(bufferlist::iterator &bl) { + InodeStoreBase::decode(bl, snap_blob); + } + void encode_bare(bufferlist &bl) const { + InodeStoreBase::encode_bare(bl, &snap_blob); + } + void decode_bare(bufferlist::iterator &bl) { + InodeStoreBase::decode_bare(bl, snap_blob); + } /* For use in debug and ceph-dencoder */ void dump(Formatter *f) const; static void generate_test_instances(std::list& ls); }; // cached inode wrapper -class CInode : public MDSCacheObject, public InodeStore { +class CInode : public MDSCacheObject, public InodeStoreBase { /* * This class uses a boost::pool to handle allocation. This is *not* * thread-safe, so don't do allocations from multiple threads! diff --git a/src/mds/MDCache.cc b/src/mds/MDCache.cc index a1a3c2217ea..385c0f9fc45 100644 --- a/src/mds/MDCache.cc +++ b/src/mds/MDCache.cc @@ -1873,7 +1873,7 @@ void MDCache::project_rstat_frag_to_inode(nest_info_t& rstat, nest_info_t& accou } else { // our life is easier here because old_inodes is not sparse // (although it may not begin at snapid 1) - map::iterator p = pin->old_inodes.lower_bound(last); + compact_map::iterator p = pin->old_inodes.lower_bound(last); if (p == pin->old_inodes.end()) { dout(10) << " no old_inode <= " << last << ", done." << dendl; break; diff --git a/src/mds/events/EMetaBlob.h b/src/mds/events/EMetaBlob.h index 60f64f859db..1fa3afe0d45 100644 --- a/src/mds/events/EMetaBlob.h +++ b/src/mds/events/EMetaBlob.h @@ -62,6 +62,7 @@ public: static const int STATE_DIRTY = (1<<0); static const int STATE_DIRTYPARENT = (1<<1); static const int STATE_DIRTYPOOL = (1<<2); + typedef compact_map old_inodes_t; string dn; // dentry snapid_t dnfirst, dnlast; version_t dnv; @@ -72,7 +73,6 @@ public: snapid_t oldest_snap; bufferlist snapbl; __u8 state; - typedef map old_inodes_t; old_inodes_t old_inodes; fullbit(const fullbit& o); diff --git a/src/mds/journal.cc b/src/mds/journal.cc index 1870ec70832..bd43ad2da94 100644 --- a/src/mds/journal.cc +++ b/src/mds/journal.cc @@ -505,7 +505,8 @@ void EMetaBlob::fullbit::dump(Formatter *f) const if (!old_inodes.empty()) { f->open_array_section("old inodes"); for (old_inodes_t::const_iterator iter = old_inodes.begin(); - iter != old_inodes.end(); ++iter) { + iter != old_inodes.end(); + ++iter) { f->open_object_section("inode"); f->dump_int("snapid", iter->first); iter->second.dump(f);