Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:31:51

0001 #ifndef STORAGE_FACTORY_STORAGE_ACCOUNT_H
0002 #define STORAGE_FACTORY_STORAGE_ACCOUNT_H
0003 
0004 #include <cstdint>
0005 #include <string>
0006 #include <chrono>
0007 #include <atomic>
0008 #include <map>
0009 #include <memory>
0010 #include "oneapi/tbb/concurrent_unordered_map.h"
0011 
0012 namespace edm::storage {
0013   class StorageAccount {
0014   public:
0015     enum class Operation {
0016       check,
0017       close,
0018       construct,
0019       destruct,
0020       flush,
0021       open,
0022       position,
0023       prefetch,
0024       read,
0025       readActual,
0026       readAsync,
0027       readPrefetchToCache,
0028       readViaCache,
0029       readv,
0030       resize,
0031       seek,
0032       stagein,
0033       stat,
0034       write,
0035       writeActual,
0036       writeViaCache,
0037       writev
0038     };
0039 
0040     struct Counter {
0041       Counter()
0042           : attempts{0},
0043             successes{0},
0044             amount{0},
0045             amount_square{0.},
0046             vector_count{0},
0047             vector_square{0},
0048             timeTotal{0.},
0049             timeMin{0.},
0050             timeMax{0.} {}
0051 
0052       //NOTE: This is needed by oneapi::tbb::concurrent_unordered_map when it
0053       // is constructing a new one. This would not give correct results
0054       // if the object being passed were being updated, but that is not
0055       // the case for operator[]
0056       Counter(Counter const& iOther)
0057           : attempts{iOther.attempts.load()},
0058             successes{iOther.successes.load()},
0059             amount{iOther.amount.load()},
0060             amount_square{iOther.amount_square.load()},
0061             vector_count{iOther.vector_count.load()},
0062             vector_square{iOther.vector_square.load()},
0063             timeTotal{iOther.timeTotal.load()},
0064             timeMin{iOther.timeMin.load()},
0065             timeMax{iOther.timeMax.load()} {}
0066 
0067       //Use atomics to allow concurrent read/write for intermediate
0068       // output of the statics while running. The values obtained
0069       // won't be completely consistent but should be good enough for
0070       // monitoring. The values obtained once the program is shutting
0071       // down should be completely consistent.
0072 
0073       std::atomic<uint64_t> attempts;
0074       std::atomic<uint64_t> successes;
0075       std::atomic<uint64_t> amount;
0076       // NOTE: Significant risk exists for underflow in this value.
0077       // However, the use cases are marginal so I let it pass.
0078       std::atomic<double> amount_square;
0079       std::atomic<int64_t> vector_count;
0080       std::atomic<int64_t> vector_square;
0081       std::atomic<double> timeTotal;
0082       std::atomic<double> timeMin;
0083       std::atomic<double> timeMax;
0084 
0085       static void addTo(std::atomic<double>& iAtomic, double iToAdd) {
0086         double oldValue = iAtomic.load();
0087         double newValue = oldValue + iToAdd;
0088         while (not iAtomic.compare_exchange_weak(oldValue, newValue)) {
0089           newValue = oldValue + iToAdd;
0090         }
0091       }
0092     };
0093 
0094     class Stamp {
0095     public:
0096       Stamp(Counter& counter);
0097 
0098       void tick(uint64_t amount = 0, int64_t tick = 0) const;
0099 
0100     protected:
0101       Counter& m_counter;
0102       std::chrono::time_point<std::chrono::steady_clock> m_start;
0103     };
0104 
0105     class StorageClassToken {
0106     public:
0107       StorageClassToken(StorageClassToken const&) = default;
0108       StorageClassToken() = delete;
0109       int value() const { return m_value; }
0110 
0111       friend class StorageAccount;
0112 
0113     private:
0114       explicit StorageClassToken(int iValue) : m_value{iValue} {}
0115 
0116       int m_value;
0117     };
0118 
0119     typedef oneapi::tbb::concurrent_unordered_map<int, Counter> OperationStats;
0120     typedef oneapi::tbb::concurrent_unordered_map<int, OperationStats> StorageStats;
0121 
0122     static char const* operationName(Operation operation);
0123     static StorageClassToken tokenForStorageClassName(std::string const& iName);
0124     static const std::string& nameForToken(StorageClassToken);
0125 
0126     static const StorageStats& summary(void);
0127     static std::string summaryText(bool banner = false);
0128     static void fillSummary(std::map<std::string, std::string>& summary);
0129     static Counter& counter(StorageClassToken token, Operation operation);
0130 
0131   private:
0132     static StorageStats m_stats;
0133   };
0134 }  // namespace edm::storage
0135 #endif  // STORAGE_FACTORY_STORAGE_ACCOUNT_H