Skip to content

Commit 2b1e1ff

Browse files
refactor(cache): move rwlock from LruEntry to FileStore, to reduce memory usage (#1149) (#1158)
* refactor(cache): lazy initialize rwlock to reduce memory usage * fix build * use defer to release Co-authored-by: xiaoyang-hhh <luxiaoyang.lxy@alibaba-inc.com>
1 parent 4f18210 commit 2b1e1ff

File tree

9 files changed

+66
-18
lines changed

9 files changed

+66
-18
lines changed

fs/cache/full_file_cache/cache_pool.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,10 @@ int FileCachePool::evict(std::string_view filename) {
135135
lru_.mark_key_cleared(lruEntry->lruIter);
136136
}
137137
int err = 0;
138+
auto cacheStore = static_cast<FileCacheStore*>(open(filePath, O_RDWR, 0644));
139+
DEFER(cacheStore->release());
138140
{
139-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::WLOCK);
141+
photon::scoped_rwlock rl(cacheStore->rw_lock(), photon::WLOCK);
140142
err = mediaFs_->truncate(filePath.data(), 0);
141143
lruEntry->truncate_done = false;
142144
}
@@ -256,8 +258,10 @@ void FileCachePool::eviction() {
256258
continue;
257259
}
258260

261+
auto cacheStore = static_cast<FileCacheStore*>(open(fileName, O_RDWR, 0644));
262+
DEFER(cacheStore->release());
259263
{
260-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::WLOCK);
264+
photon::scoped_rwlock rl(cacheStore->rw_lock(), photon::WLOCK);
261265
err = mediaFs_->truncate(fileName.data(), 0);
262266
lruEntry->truncate_done = false;
263267
}

fs/cache/full_file_cache/cache_pool.h

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,6 @@ class FileCachePool : public photon::fs::ICachePool {
4545

4646
void Init();
4747

48-
// pathname must begin with '/'
49-
photon::fs::ICacheStore *do_open(std::string_view pathname, int flags, mode_t mode) override;
50-
5148
int set_quota(std::string_view pathname, size_t quota) override;
5249
int stat(photon::fs::CacheStat *stat,
5350
std::string_view pathname = std::string_view(nullptr, 0)) override;
@@ -64,7 +61,6 @@ class FileCachePool : public photon::fs::ICachePool {
6461
uint32_t lruIter;
6562
int openCount;
6663
uint64_t size;
67-
photon::rwlock rw_lock_;
6864
bool truncate_done;
6965
};
7066

@@ -81,6 +77,8 @@ class FileCachePool : public photon::fs::ICachePool {
8177
uint64_t updateSpace(FileNameMap::iterator iter, uint64_t size);
8278

8379
protected:
80+
// pathname must begin with '/'
81+
photon::fs::ICacheStore *do_open(std::string_view pathname, int flags, mode_t mode) override;
8482
photon::fs::IFile *openMedia(std::string_view name, int flags, int mode);
8583

8684
static uint64_t timerHandler(void *data);

fs/cache/full_file_cache/cache_store.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ FileCacheStore::~FileCacheStore() {
5151

5252
ICacheStore::try_preadv_result FileCacheStore::try_preadv2(const struct iovec *iov, int iovcnt,
5353
off_t offset, int flags) {
54-
auto lruEntry = static_cast<FileCachePool::LruEntry *>(iterator_->second.get());
55-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::RLOCK);
54+
photon::scoped_rwlock rl(rw_lock_, photon::RLOCK);
5655
return this->ICacheStore::try_preadv2(iov, iovcnt, offset, flags);
5756
}
5857

@@ -70,8 +69,8 @@ ssize_t FileCacheStore::do_pwritev(const struct iovec *iov, int iovcnt, off_t of
7069
{
7170
ssize_t ret;
7271
iovector_view view((iovec*)iov, iovcnt);
73-
auto lruEntry = static_cast<FileCachePool::LruEntry *>(iterator_->second.get());
74-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::RLOCK);
72+
auto lruEntry = iterator_->second.get();
73+
photon::scoped_rwlock rl(rw_lock_, photon::RLOCK);
7574
if (!lruEntry->truncate_done) {
7675
// May repeated ftruncate() here, but it doesn't matter
7776
ret = localFile_->ftruncate(actual_size_);

fs/cache/full_file_cache/cache_store.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ class FileCacheStore : public photon::fs::ICacheStore {
4747

4848
int fstat(struct stat *buf) override;
4949

50+
photon::rwlock &rw_lock() { return rw_lock_; }
51+
5052
protected:
5153
bool cacheIsFull();
5254

@@ -70,6 +72,8 @@ class FileCacheStore : public photon::fs::ICacheStore {
7072
FileIterator iterator_;
7173
RangeLock rangeLock_;
7274

75+
photon::rwlock rw_lock_;
76+
7377
ssize_t do_pwritev(const struct iovec *iov, int iovcnt, off_t offset);
7478
};
7579

fs/cache/full_file_cache/quota_pool.cpp

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -194,8 +194,11 @@ int QuotaFilePool::evict(std::string_view filename) {
194194
const auto& filePath = fileIter->first;
195195
int err;
196196
auto lruEntry = static_cast<QuotaLruEntry*>(fileIter->second.get());
197+
198+
auto cacheStore = static_cast<FileCacheStore*>(open(filePath, O_RDWR, 0644));
199+
DEFER(cacheStore->release());
197200
{
198-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::WLOCK);
201+
photon::scoped_rwlock rl(cacheStore->rw_lock(), photon::WLOCK);
199202
lru.mark_key_cleared(lruEntry->QuotaLruIter);
200203
err = mediaFs_->truncate(filePath.data(), 0);
201204
if (err) {
@@ -234,15 +237,19 @@ void QuotaFilePool::dirEviction() {
234237
auto lruEntry = static_cast<QuotaLruEntry*>(fileIter->second.get());
235238
int err;
236239
bool flags_dir_delete = false;
240+
241+
auto cacheStore = static_cast<FileCacheStore*>(open(fileName, O_RDWR, 0644));
242+
DEFER(cacheStore->release());
237243
{
238-
photon::scoped_rwlock rl(lruEntry->rw_lock_, photon::WLOCK);
244+
photon::scoped_rwlock rl(cacheStore->rw_lock(), photon::WLOCK);
239245
if (lruEntry->openCount==0){
240246
dir->lru.mark_key_cleared(lruEntry->QuotaLruIter);
241247
} else {
242248
dir->lru.access(lruEntry->QuotaLruIter);
243249
}
244250
err = mediaFs_->truncate(fileName.data(), 0);
245251
}
252+
246253
if (err) {
247254
ERRNO e;
248255
LOG_ERROR("truncate(0) failed, name : `, ret : `, error code : `", fileName, err, e);

fs/cache/full_file_cache/quota_pool.h

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,6 @@ class QuotaFilePool : public FileCachePool {
2727
QuotaFilePool(photon::fs::IFileSystem* mediaFs, uint64_t capacityInGB, uint64_t periodInUs,
2828
uint64_t diskAvailInBytes, uint64_t refillUnit, int quotaDirLevel);
2929

30-
photon::fs::ICacheStore* do_open(std::string_view pathname, int flags, mode_t mode) override;
31-
3230
void updateDirLru(FileIterator iter);
3331

3432
bool dirSpaceIsFull(FileIterator iter);
@@ -42,6 +40,7 @@ class QuotaFilePool : public FileCachePool {
4240
int evict(std::string_view filename) override;
4341

4442
protected:
43+
photon::fs::ICacheStore* do_open(std::string_view pathname, int flags, mode_t mode) override;
4544
void dirEviction();
4645

4746
bool afterFtrucate(FileIterator iter) override;

fs/cache/full_file_cache/quota_store.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ ssize_t QuotaFileStore::do_pwritev2(const struct iovec *iov, int iovcnt, off_t o
5656
}
5757
ssize_t ret;
5858
{
59-
auto lruEntry = static_cast<FileCachePool::LruEntry*>(iterator_->second.get());
60-
photon::scoped_rwlock wl(lruEntry->rw_lock_, photon::WLOCK);
59+
photon::scoped_rwlock wl(rw_lock_, photon::WLOCK);
6160
ret = localFile_->pwritev(iov, iovcnt, offset);
6261
}
6362
if (ret < 0 && ENOSPC == errno) {

fs/cache/pool_store.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ namespace fs
108108

109109
void set_trans_func(CacheFnTransFunc fn_trans_func);
110110

111-
virtual ICacheStore* do_open(std::string_view filename, int flags, mode_t mode) = 0;
112-
113111
virtual int rename(std::string_view oldname, std::string_view newname) = 0;
114112

115113
virtual ssize_t list(const char* dirname, ListType type,
@@ -146,6 +144,8 @@ namespace fs
146144
}
147145

148146
protected:
147+
virtual ICacheStore* do_open(std::string_view filename, int flags, mode_t mode) = 0;
148+
149149
void* m_stores;
150150
CacheFnTransFunc fn_trans_func;
151151
void* m_thread_pool = nullptr;

fs/cache/test/cache_test.cpp

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,44 @@ TEST(CachePool, random_evict_file) {
676676
if (cacheStore) cacheStore->release();
677677
}
678678

679+
TEST(CachePool, open_same_file) {
680+
std::string root = "/tmp/ease/cache/open_same_file/";
681+
SetupTestDir(root);
682+
auto mediaFs = new_localfs_adaptor(root.c_str(), ioengine_libaio);
683+
auto alignFs = new_aligned_fs_adaptor(mediaFs, 4 * 1024, true, true);
684+
auto cacheAllocator = new AlignedAlloc(4 * 1024);
685+
auto roCachedFs = new_full_file_cached_fs(nullptr, alignFs, 1024 * 1024,
686+
1, 1000 * 1000 * 1, 128ul * 1024 * 1024, cacheAllocator, 0);
687+
auto cachePool = roCachedFs->get_pool();
688+
DEFER({ delete cacheAllocator; delete roCachedFs; });
689+
690+
auto fileName = "/testDir/testfile";
691+
692+
uint64_t written = 0;
693+
for (int j = 0; j < 5; j++) {
694+
std::vector<ICacheStore*> cacheStores;
695+
for (int i = 0; i < 10; i++) {
696+
cacheStores.push_back(cachePool->open(fileName, O_CREAT | O_RDWR, 0644));
697+
ASSERT_NE(nullptr, cacheStores.back());
698+
}
699+
700+
const size_t bufSize = 1024 * 1024;
701+
IOVector buffer(*cacheAllocator);
702+
buffer.push_back(bufSize);
703+
704+
for (auto cacheStore : cacheStores) {
705+
if (rand() % 2 == 0) {
706+
cacheStore->release();
707+
} else {
708+
auto ret = cacheStore->do_pwritev2(buffer.iovec(), buffer.iovcnt(), written, 0);
709+
EXPECT_EQ(ret, (ssize_t)bufSize);
710+
written += ret;
711+
cacheStore->release();
712+
}
713+
}
714+
}
715+
}
716+
679717
}
680718
}
681719
int main(int argc, char** argv) {

0 commit comments

Comments
 (0)