Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Zolotarev <deathbaba@gmail.com>2010-12-05 19:24:16 +0300
committerAlex Zolotarev <alex@maps.me>2015-09-22 22:33:57 +0300
commitd6e12b7ce4bcbf0ccd1c07eb25de143422913c34 (patch)
treea7e910c330ce4da9b4f2d8be76067adece2561c4 /coding/reader_cache.hpp
One Month In Minsk. Made in Belarus.
Diffstat (limited to 'coding/reader_cache.hpp')
-rw-r--r--coding/reader_cache.hpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/coding/reader_cache.hpp b/coding/reader_cache.hpp
new file mode 100644
index 0000000000..6247ba857f
--- /dev/null
+++ b/coding/reader_cache.hpp
@@ -0,0 +1,104 @@
+#pragma once
+#include "reader.hpp"
+#include "../base/base.hpp"
+#include "../base/cache.hpp"
+#include "../base/logging.hpp"
+#include "../base/stats.hpp"
+#include "../std/scoped_ptr.hpp"
+#include "../std/vector.hpp"
+
+namespace impl
+{
+
+template <bool bEnable> struct ReaderCacheStats
+{
+ string GetStatsStr(uint32_t, uint32_t) const { return ""; }
+ my::NoopStats<uint32_t> m_ReadSize;
+ my::NoopStats<uint32_t> m_CacheHit;
+};
+
+template <> struct ReaderCacheStats<true>
+{
+ string GetStatsStr(uint32_t logPageSize, uint32_t pageCount) const
+ {
+ ostringstream out;
+ out << "LogPageSize: " << logPageSize << " PageCount: " << pageCount;
+ out << " ReadSize(" << m_ReadSize.GetStatsStr() << ")";
+ out << " CacheHit(" << m_CacheHit.GetStatsStr() << ")";
+ double const bytesAsked = m_ReadSize.GetAverage() * m_ReadSize.GetCount();
+ double const callsMade = (1.0 - m_CacheHit.GetAverage()) * m_CacheHit.GetCount();
+ double const bytesRead = callsMade * (1 << logPageSize);
+ out << " RatioBytesRead: " << (bytesRead + 1) / (bytesAsked + 1);
+ out << " RatioCallsMade: " << (callsMade + 1) / (m_ReadSize.GetCount() + 1);
+ return out.str();
+ }
+
+ my::AverageStats<uint32_t> m_ReadSize;
+ my::AverageStats<uint32_t> m_CacheHit;
+};
+
+}
+
+template <class ReaderT, bool bStats = false>
+class ReaderCache
+{
+public:
+ ReaderCache(uint32_t logPageSize, uint32_t logPageCount)
+ : m_Cache(logPageCount), m_LogPageSize(logPageSize)
+ {
+ }
+
+ void Read(ReaderT & reader, uint64_t pos, void * p, size_t size)
+ {
+ if (size == 0)
+ return;
+ ASSERT_LESS_OR_EQUAL(pos + size, reader.Size(), (pos, size, reader.Size()));
+ m_Stats.m_ReadSize(size);
+ char * pDst = static_cast<char *>(p);
+ uint64_t pageNum = pos >> m_LogPageSize;
+ size_t const firstPageOffset = static_cast<size_t>(pos - (pageNum << m_LogPageSize));
+ size_t const firstCopySize = min(size, PageSize() - firstPageOffset);
+ ASSERT_GREATER(firstCopySize, 0, ());
+ memcpy(pDst, ReadPage(reader, pageNum) + firstPageOffset, firstCopySize);
+ size -= firstCopySize;
+ pos += firstCopySize;
+ pDst += firstCopySize;
+ ++pageNum;
+ while (size > 0)
+ {
+ size_t const copySize = min(size, PageSize());
+ memcpy(pDst, ReadPage(reader, pageNum), copySize);
+ size -= copySize;
+ pos += copySize;
+ pDst += copySize;
+ ++pageNum;
+ }
+ }
+
+ string GetStatsStr() const
+ {
+ return m_Stats.GetStatsStr(m_LogPageSize, m_Cache.GetCacheSize());
+ }
+
+private:
+ inline size_t PageSize() const { return 1 << m_LogPageSize; }
+
+ inline char const * ReadPage(ReaderT & reader, uint64_t pageNum)
+ {
+ bool cached;
+ vector<char> & v = m_Cache.Find(pageNum, cached);
+ m_Stats.m_CacheHit(cached ? 1 : 0);
+ if (!cached)
+ {
+ if (v.empty())
+ v.resize(PageSize());
+ uint64_t const pos = pageNum << m_LogPageSize;
+ reader.Read(pos, &v[0], min(PageSize(), static_cast<size_t>(reader.Size() - pos)));
+ }
+ return &v[0];
+ }
+
+ my::Cache<uint64_t, vector<char> > m_Cache;
+ uint32_t const m_LogPageSize;
+ impl::ReaderCacheStats<bStats> m_Stats;
+};