From: Yan, Zheng Date: Fri, 6 Feb 2015 11:02:31 +0000 (+0800) Subject: introduce compact_set and compact_map X-Git-Tag: v9.0.0~201^2~11 X-Git-Url: http://git-server-git.apps.pok.os.sepia.ceph.com/?a=commitdiff_plain;h=c57df9c4e6f09c996fa0f54189501be085322b1b;p=ceph.git introduce compact_set and compact_map They are wrapper classes of std::set and std::map, which only contain a pointer to the actual std::set/std::map. They are aimed for replacing std::set/std::map for class members which are rarely used and mostly empty. Replacing each std::set/std::map can save 40 bytes for 64 bits program. Signed-off-by: Yan, Zheng --- diff --git a/src/include/Makefile.am b/src/include/Makefile.am index e0952d95e82..06db326fea8 100644 --- a/src/include/Makefile.am +++ b/src/include/Makefile.am @@ -72,6 +72,8 @@ noinst_HEADERS += \ include/elist.h \ include/uuid.h \ include/xlist.h \ + include/compact_map.h \ + include/compact_set.h \ include/rados/librados.h \ include/rados/rados_types.h \ include/rados/rados_types.hpp \ diff --git a/src/include/compact_map.h b/src/include/compact_map.h new file mode 100644 index 00000000000..a530c27130d --- /dev/null +++ b/src/include/compact_map.h @@ -0,0 +1,347 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Red Hat, Inc + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ +#ifndef CEPH_COMPACT_MAP_H +#define CEPH_COMPACT_MAP_H + +#include + +template +class compact_map_base { +protected: + Map *map; + void alloc_internal() { + if (!map) + map = new Map; + } + void free_internal() { + if (map) { + delete map; + map = 0; + } + } + template + class const_iterator_base { + const compact_map_base *map; + It it; + const_iterator_base() : map(0) { } + const_iterator_base(const compact_map_base* m) : map(m) { } + const_iterator_base(const compact_map_base *m, const It& i) : map(m), it(i) { } + friend class compact_map_base; + friend class iterator_base; + public: + const_iterator_base(const const_iterator_base& o) { + map = o.map; + it = o.it; + } + bool operator==(const const_iterator_base& o) const { + return (map == o.map) && (!map->map || it == o.it); + } + bool operator!=(const const_iterator_base& o) const { + return !(*this == o);; + } + const_iterator_base& operator=(const const_iterator_base& o) { + map = o.map; + it = o.it; + return *this; + } + const_iterator_base& operator++() { + ++it; + return *this; + } + const_iterator_base& operator--() { + --it; + return *this; + } + const std::pair* operator->() { + return it.operator->(); + } + }; + template + class iterator_base { + private: + const compact_map_base* map; + It it; + iterator_base() : map(0) { } + iterator_base(compact_map_base* m) : map(m) { } + iterator_base(compact_map_base* m, const It& i) : map(m), it(i) { } + friend class compact_map_base; + public: + iterator_base(const iterator_base& o) { + map = o.map; + it = o.it; + } + bool operator==(const iterator_base& o) const { + return (map == o.map) && (!map->map || it == o.it); + } + bool operator!=(const iterator_base& o) const { + return !(*this == o);; + } + iterator_base& operator=(const iterator_base& o) { + map = o.map; + it = o.it; + return *this; + } + iterator_base& operator++() { + ++it; + return *this; + } + iterator_base operator++(int) { + iterator_base tmp = *this; + ++it; + return tmp; + } + iterator_base& operator--() { + --it; + return *this; + } + std::pair* operator->() { + return it.operator->(); + } + operator const_iterator_base() const { + return const_iterator_base(map, it); + } + }; + +public: + class iterator : public iterator_base { + public: + iterator() { } + iterator(const iterator_base& o) + : iterator_base(o) { } + iterator(compact_map_base* m) : iterator_base(m) { } + iterator(compact_map_base* m, const typename Map::iterator& i) + : iterator_base(m, i) { } + }; + class const_iterator : public const_iterator_base { + public: + const_iterator() { } + const_iterator(const iterator_base& o) + : const_iterator_base(o) { } + const_iterator(const compact_map_base* m) : const_iterator_base(m) { } + const_iterator(const compact_map_base* m, const typename Map::const_iterator& i) + : const_iterator_base(m, i) { } + }; + class reverse_iterator : public iterator_base { + public: + reverse_iterator() { } + reverse_iterator(const iterator_base& o) + : iterator_base(o) { } + reverse_iterator(compact_map_base* m) : iterator_base(m) { } + reverse_iterator(compact_map_base* m, const typename Map::reverse_iterator& i) + : iterator_base(m, i) { } + }; + class const_reverse_iterator : public const_iterator_base { + public: + const_reverse_iterator() { } + const_reverse_iterator(const iterator_base& o) + : iterator_base(o) { } + const_reverse_iterator(const compact_map_base* m) : const_iterator_base(m) { } + const_reverse_iterator(const compact_map_base* m, const typename Map::const_reverse_iterator& i) + : const_iterator_base(m, i) { } + }; + compact_map_base() : map(0) {} + compact_map_base(const compact_map_base& o) : map(0) { + if (o.map) { + alloc_internal(); + *map = *o.map; + } + } + ~compact_map_base() { delete map; } + + bool empty() const { + return !map || map->empty(); + } + size_t size() const { + return map ? map->size() : 0; + } + bool operator==(const compact_map_base& o) const { + return (empty() && o.empty()) || (map && o.map && *map == *o.map); + } + bool operator!=(const compact_map_base& o) const { + return !(*this == o); + } + size_t count (const Key& k) const { + return map ? map->count(k) : 0; + } + void erase (iterator p) { + if (map) { + assert(this == p.map); + map->erase(p.it); + if (map->empty()) + free_internal(); + } + } + size_t erase (const Key& k) { + if (!map) + return 0; + size_t r = map->erase(k); + if (map->empty()) + free_internal(); + return r; + } + void clear() { + free_internal(); + } + void swap(compact_map_base& o) { + Map *tmp = map; + map = o.map; + o.map = tmp; + } + compact_map_base& operator=(const compact_map_base& o) { + if (o.map) { + alloc_internal(); + *map = *o.map; + } else + free_internal(); + return *this; + } + iterator insert(const std::pair& val) { + alloc_internal(); + return iterator(this, map->insert(val)); + } + iterator begin() { + if (!map) + return iterator(this); + return iterator(this, map->begin()); + } + iterator end() { + if (!map) + return iterator(this); + return iterator(this, map->end()); + } + reverse_iterator rbegin() { + if (!map) + return reverse_iterator(this); + return reverse_iterator(this, map->rbegin()); + } + reverse_iterator rend() { + if (!map) + return reverse_iterator(this); + return reverse_iterator(this, map->rend()); + } + iterator find(const Key& k) { + if (!map) + return iterator(this); + return iterator(this, map->find(k)); + } + iterator lower_bound(const Key& k) { + if (!map) + return iterator(this); + return iterator(this, map->lower_bound(k)); + } + iterator upper_bound(const Key& k) { + if (!map) + return iterator(this); + return iterator(this, map->upper_bound(k)); + } + const_iterator begin() const { + if (!map) + return const_iterator(this); + return const_iterator(this, map->begin()); + } + const_iterator end() const { + if (!map) + return const_iterator(this); + return const_iterator(this, map->end()); + } + const_reverse_iterator rbegin() const { + if (!map) + return const_reverse_iterator(this); + return const_reverse_iterator(this, map->rbegin()); + } + const_reverse_iterator rend() const { + if (!map) + return const_reverse_iterator(this); + return const_reverse_iterator(this, map->rend()); + } + const_iterator find(const Key& k) const { + if (!map) + return const_iterator(this); + return const_iterator(this, map->find(k)); + } + const_iterator lower_bound(const Key& k) const { + if (!map) + return const_iterator(this); + return const_iterator(this, map->lower_bound(k)); + } + const_iterator upper_bound(const Key& k) const { + if (!map) + return const_iterator(this); + return const_iterator(this, map->upper_bound(k)); + } + void encode(bufferlist &bl) const { + if (map) + ::encode(*map, bl); + else + ::encode((uint32_t)0, bl); + } + void decode(bufferlist::iterator& p) { + uint32_t n; + ::decode(n, p); + if (n > 0) { + alloc_internal(); + ::decode_nohead(n, *map, p); + } else + free_internal(); + } +}; + +template +inline void encode(const compact_map_base& m, bufferlist& bl) { + m.encode(bl); +} +template +inline void decode(compact_map_base& m, bufferlist::iterator& p) { + m.decode(p); +} + +template +class compact_map : public compact_map_base > { +public: + T& operator[](const Key& k) { + this->alloc_internal(); + return (*(this->map))[k]; + } +}; + +template +inline std::ostream& operator<<(std::ostream& out, const compact_map& m) +{ + out << "{"; + for (typename compact_map::const_iterator it = m.begin(); + it != m.end(); + ++it) { + if (it != m.begin()) + out << ","; + out << it->first << "=" << it->second; + } + out << "}"; + return out; +} + +template +class compact_multimap : public compact_map_base > { +}; + +template +inline std::ostream& operator<<(std::ostream& out, const compact_multimap& m) +{ + out << "{{"; + for (typename compact_map::const_iterator it = m.begin(); !it.end(); ++it) { + if (it != m.begin()) + out << ","; + out << it->first << "=" << it->second; + } + out << "}}"; + return out; +} +#endif diff --git a/src/include/compact_set.h b/src/include/compact_set.h new file mode 100644 index 00000000000..fcd847baff8 --- /dev/null +++ b/src/include/compact_set.h @@ -0,0 +1,290 @@ +/* + * Ceph - scalable distributed file system + * + * Copyright (C) 2015 Red Hat, Inc + * + * This is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License version 2.1, as published by the Free Software + * Foundation. See file COPYING. + * + */ +#ifndef CEPH_COMPACT_SET_H +#define CEPH_COMPACT_SET_H + +#include + +template +class compact_set_base { +protected: + Set *set; + void alloc_internal() { + if (!set) + set = new Set; + } + void free_internal() { + if (set) { + delete set; + set = 0; + } + } + template + class iterator_base { + private: + const compact_set_base* set; + It it; + iterator_base() : set(0) { } + iterator_base(const compact_set_base* s) : set(s) { } + iterator_base(const compact_set_base* s, const It& i) : set(s), it(i) { } + friend class compact_set_base; + public: + iterator_base(const iterator_base& o) { + set = o.set; + it = o.it; + } + bool operator==(const iterator_base& o) const { + return (set == o.set) && (!set->set || it == o.it); + } + bool operator!=(const iterator_base& o) const { + return !(*this == o);; + } + iterator_base& operator=(const iterator_base& o) { + set->set = o.set; + it = o.it; + return *this; + } + iterator_base& operator++() { + ++it; + return *this; + } + iterator_base operator++(int) { + iterator_base tmp = *this; + ++it; + return tmp; + } + iterator_base& operator--() { + --it; + return *this; + } + const T& operator*() { + return *it; + } + }; +public: + class const_iterator : public iterator_base { + public: + const_iterator() { } + const_iterator(const iterator_base& o) + : iterator_base(o) { } + const_iterator(const compact_set_base* s) : iterator_base(s) { } + const_iterator(const compact_set_base* s, const typename Set::const_iterator& i) + : iterator_base(s, i) { } + }; + class iterator : public iterator_base { + public: + iterator() { } + iterator(const iterator_base& o) + : iterator_base(o) { } + iterator(compact_set_base* s) : iterator_base(s) { } + iterator(compact_set_base* s, const typename Set::iterator& i) + : iterator_base(s, i) { } + operator const_iterator() const { + return const_iterator(this->set, this->it); + } + }; + class const_reverse_iterator : public iterator_base { + public: + const_reverse_iterator() { } + const_reverse_iterator(const iterator_base& o) + : iterator_base(o) { } + const_reverse_iterator(const compact_set_base* s) : iterator_base(s) { } + const_reverse_iterator(const compact_set_base* s, const typename Set::const_reverse_iterator& i) + : iterator_base(s, i) { } + }; + class reverse_iterator : public iterator_base { + public: + reverse_iterator() { } + reverse_iterator(const iterator_base& o) + : iterator_base(o) { } + reverse_iterator(compact_set_base* s) : iterator_base(s) { } + reverse_iterator(compact_set_base* s, const typename Set::reverse_iterator& i) + : iterator_base(s, i) { } + operator const_iterator() const { + return const_iterator(this->set, this->it); + } + }; + + compact_set_base() : set(0) {} + compact_set_base(const compact_set_base& o) : set(0) { + if (o.set) { + alloc_internal(); + *set = *o.set; + } + } + ~compact_set_base() { delete set; } + + + bool empty() const { + return !set || set->empty(); + } + size_t size() const { + return set ? set->size() : 0; + } + bool operator==(const compact_set_base& o) const { + return (empty() && o.empty()) || (set && o.set && *set == *o.set); + } + bool operator!=(const compact_set_base& o) const { + return !(*this == o); + } + size_t count(const T& t) const { + return set ? set->count(t) : 0; + } + void erase (iterator p) { + if (set) { + assert(this == p.set); + set->erase(p.it); + if (set->empty()) + free_internal(); + } + } + size_t erase (const T& t) { + if (!set) + return 0; + size_t r = set->erase(t); + if (set->empty()) + free_internal(); + return r; + } + void clear() { + free_internal(); + } + void swap(compact_set_base& o) { + Set *tmp = set; + set = o.set; + o.set = tmp; + } + compact_set_base& operator=(const compact_set_base& o) { + if (o.set) { + alloc_internal(); + *set = *o.set; + } else + free_internal(); + return *this; + } + std::pair insert(const T& t) { + alloc_internal(); + std::pair r = set->insert(t); + return std::make_pair(iterator(this, r.first), r.second); + } + iterator begin() { + if (!set) + return iterator(this); + return iterator(this, set->begin()); + } + iterator end() { + if (!set) + return iterator(this); + return iterator(this, set->end()); + } + reverse_iterator rbegin() { + if (!set) + return reverse_iterator(this); + return reverse_iterator(this, set->rbegin()); + } + reverse_iterator rend() { + if (!set) + return reverse_iterator(this); + return reverse_iterator(this, set->rend()); + } + iterator find(const T& t) { + if (!set) + return iterator(this); + return iterator(this, set->find(t)); + } + iterator lower_bound(const T& t) { + if (!set) + return iterator(this); + return iterator(this, set->lower_bound(t)); + } + iterator upper_bound(const T& t) { + if (!set) + return iterator(this); + return iterator(this, set->upper_bound(t)); + } + const_iterator begin() const { + if (!set) + return const_iterator(this); + return const_iterator(this, set->begin()); + } + const_iterator end() const { + if (!set) + return const_iterator(this); + return const_iterator(this, set->end()); + } + const_reverse_iterator rbegin() const { + if (!set) + return const_reverse_iterator(this); + return const_reverse_iterator(this, set->rbegin()); + } + const_reverse_iterator rend() const { + if (!set) + return const_reverse_iterator(this); + return const_reverse_iterator(this, set->rend()); + } + const_iterator find(const T& t) const { + if (!set) + return const_iterator(this); + return const_iterator(this, set->find(t)); + } + const_iterator lower_bound(const T& t) const { + if (!set) + return const_iterator(this); + return const_iterator(this, set->lower_bound(t)); + } + const_iterator upper_bound(const T& t) const { + if (!set) + return const_iterator(this); + return const_iterator(this, set->upper_bound(t)); + } + void encode(bufferlist &bl) const { + if (set) + ::encode(*set, bl); + else + ::encode((uint32_t)0, bl); + } + void decode(bufferlist::iterator& p) { + uint32_t n; + ::decode(n, p); + if (n > 0) { + alloc_internal(); + ::decode_nohead(n, *set, p); + } else + free_internal(); + } +}; + +template +inline void encode(const compact_set_base& m, bufferlist& bl) { + m.encode(bl); +} +template +inline void decode(compact_set_base& m, bufferlist::iterator& p) { + m.decode(p); +} + +template +class compact_set : public compact_set_base > { +}; + +template +inline std::ostream& operator<<(std::ostream& out, const compact_set& s) +{ + for (typename compact_set::const_iterator it = s.begin(); + it != s.end(); ++it) { + if (it != s.begin()) + out << ","; + out << it->first << "=" << it->second; + } + return out; +} +#endif diff --git a/src/include/encoding.h b/src/include/encoding.h index 7b976f24b57..b190111d1c0 100644 --- a/src/include/encoding.h +++ b/src/include/encoding.h @@ -453,6 +453,22 @@ inline void decode(std::set& s, bufferlist::iterator& p) } } +template +inline void encode_nohead(const std::set& s, bufferlist& bl) +{ + for (typename std::set::const_iterator p = s.begin(); p != s.end(); ++p) + encode(*p, bl); +} +template +inline void decode_nohead(int len, std::set& s, bufferlist::iterator& p) +{ + for (int i=0; i inline void encode(const std::multiset& s, bufferlist& bl)