mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-22 18:54:02 +01:00
Support: Add a cache pruning policy parser.
The idea is that the policy string fully specifies the policy and is portable between clients. Differential Revision: https://reviews.llvm.org/D31020 llvm-svn: 297927
This commit is contained in:
parent
904fab62c8
commit
d7d9d85053
@ -142,12 +142,6 @@ public:
|
||||
struct CachingOptions {
|
||||
std::string Path; // Path to the cache, empty to disable.
|
||||
CachePruningPolicy Policy;
|
||||
|
||||
CachingOptions() {
|
||||
Policy.Interval = std::chrono::seconds(1200);
|
||||
Policy.Expiration = std::chrono::hours(7 * 24); // 1w
|
||||
Policy.PercentageOfAvailableSpace = 75;
|
||||
};
|
||||
};
|
||||
|
||||
/// Provide a path to a directory where to store the cached files for
|
||||
|
@ -20,25 +20,36 @@
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename T> class Expected;
|
||||
|
||||
/// Policy for the pruneCache() function. A default constructed
|
||||
/// CachePruningPolicy provides a reasonable default policy.
|
||||
struct CachePruningPolicy {
|
||||
/// The pruning interval. This is intended to be used to avoid scanning the
|
||||
/// directory too often. It does not impact the decision of which file to
|
||||
/// prune. A value of 0 forces the scan to occur.
|
||||
std::chrono::seconds Interval = std::chrono::seconds::zero();
|
||||
std::chrono::seconds Interval = std::chrono::seconds(1200);
|
||||
|
||||
/// The expiration for a file. When a file hasn't been accessed for Expiration
|
||||
/// seconds, it is removed from the cache. A value of 0 disables the
|
||||
/// expiration-based pruning.
|
||||
std::chrono::seconds Expiration = std::chrono::seconds::zero();
|
||||
std::chrono::seconds Expiration = std::chrono::hours(7 * 24); // 1w
|
||||
|
||||
/// The maximum size for the cache directory, in terms of percentage of the
|
||||
/// available space on the the disk. Set to 100 to indicate no limit, 50 to
|
||||
/// indicate that the cache size will not be left over half the available disk
|
||||
/// space. A value over 100 will be reduced to 100. A value of 0 disables the
|
||||
/// size-based pruning.
|
||||
unsigned PercentageOfAvailableSpace = 0;
|
||||
unsigned PercentageOfAvailableSpace = 75;
|
||||
};
|
||||
|
||||
/// Parse the given string as a cache pruning policy. Defaults are taken from a
|
||||
/// default constructed CachePruningPolicy object.
|
||||
/// For example: "prune_interval=30s:prune_after=24h:cache_size=50%"
|
||||
/// which means a pruning interval of 30 seconds, expiration time of 24 hours
|
||||
/// and maximum cache size of 50% of available disk space.
|
||||
Expected<CachePruningPolicy> parseCachePruningPolicy(StringRef PolicyStr);
|
||||
|
||||
/// Peform pruning using the supplied policy, returns true if pruning
|
||||
/// occured, i.e. if Policy.Interval was expired.
|
||||
bool pruneCache(StringRef Path, CachePruningPolicy Policy);
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
#include "llvm/Support/Debug.h"
|
||||
#include "llvm/Support/Errc.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
#include "llvm/Support/Path.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
@ -33,6 +34,73 @@ static void writeTimestampFile(StringRef TimestampFile) {
|
||||
raw_fd_ostream Out(TimestampFile.str(), EC, sys::fs::F_None);
|
||||
}
|
||||
|
||||
static Expected<std::chrono::seconds> parseDuration(StringRef Duration) {
|
||||
if (Duration.empty())
|
||||
return make_error<StringError>("Duration must not be empty",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
StringRef NumStr = Duration.slice(0, Duration.size()-1);
|
||||
uint64_t Num;
|
||||
if (NumStr.getAsInteger(0, Num))
|
||||
return make_error<StringError>("'" + NumStr + "' not an integer",
|
||||
inconvertibleErrorCode());
|
||||
|
||||
switch (Duration.back()) {
|
||||
case 's':
|
||||
return std::chrono::seconds(Num);
|
||||
case 'm':
|
||||
return std::chrono::minutes(Num);
|
||||
case 'h':
|
||||
return std::chrono::hours(Num);
|
||||
default:
|
||||
return make_error<StringError>("'" + Duration +
|
||||
"' must end with one of 's', 'm' or 'h'",
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
Expected<CachePruningPolicy>
|
||||
llvm::parseCachePruningPolicy(StringRef PolicyStr) {
|
||||
CachePruningPolicy Policy;
|
||||
std::pair<StringRef, StringRef> P = {"", PolicyStr};
|
||||
while (!P.second.empty()) {
|
||||
P = P.second.split(':');
|
||||
|
||||
StringRef Key, Value;
|
||||
std::tie(Key, Value) = P.first.split('=');
|
||||
if (Key == "prune_interval") {
|
||||
auto DurationOrErr = parseDuration(Value);
|
||||
if (!DurationOrErr)
|
||||
return std::move(DurationOrErr.takeError());
|
||||
Policy.Interval = *DurationOrErr;
|
||||
} else if (Key == "prune_after") {
|
||||
auto DurationOrErr = parseDuration(Value);
|
||||
if (!DurationOrErr)
|
||||
return std::move(DurationOrErr.takeError());
|
||||
Policy.Expiration = *DurationOrErr;
|
||||
} else if (Key == "cache_size") {
|
||||
if (Value.back() != '%')
|
||||
return make_error<StringError>("'" + Value + "' must be a percentage",
|
||||
inconvertibleErrorCode());
|
||||
StringRef SizeStr = Value.slice(0, Value.size() - 1);
|
||||
uint64_t Size;
|
||||
if (SizeStr.getAsInteger(0, Size))
|
||||
return make_error<StringError>("'" + SizeStr + "' not an integer",
|
||||
inconvertibleErrorCode());
|
||||
if (Size > 100)
|
||||
return make_error<StringError>("'" + SizeStr +
|
||||
"' must be between 0 and 100",
|
||||
inconvertibleErrorCode());
|
||||
Policy.PercentageOfAvailableSpace = Size;
|
||||
} else {
|
||||
return make_error<StringError>("Unknown key: '" + Key + "'",
|
||||
inconvertibleErrorCode());
|
||||
}
|
||||
}
|
||||
|
||||
return Policy;
|
||||
}
|
||||
|
||||
/// Prune the cache of files that haven't been accessed in a long time.
|
||||
bool llvm::pruneCache(StringRef Path, CachePruningPolicy Policy) {
|
||||
using namespace std::chrono;
|
||||
|
@ -10,6 +10,7 @@ add_llvm_unittest(SupportTests
|
||||
BinaryStreamTest.cpp
|
||||
BlockFrequencyTest.cpp
|
||||
BranchProbabilityTest.cpp
|
||||
CachePruningTest.cpp
|
||||
Casting.cpp
|
||||
Chrono.cpp
|
||||
CommandLineTest.cpp
|
||||
|
71
unittests/Support/CachePruningTest.cpp
Normal file
71
unittests/Support/CachePruningTest.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
//===- CachePruningTest.cpp -----------------------------------------------===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "llvm/Support/CachePruning.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
TEST(CachePruningPolicyParser, Empty) {
|
||||
auto P = parseCachePruningPolicy("");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
|
||||
EXPECT_EQ(std::chrono::hours(7 * 24), P->Expiration);
|
||||
EXPECT_EQ(75u, P->PercentageOfAvailableSpace);
|
||||
}
|
||||
|
||||
TEST(CachePruningPolicyParser, Interval) {
|
||||
auto P = parseCachePruningPolicy("prune_interval=1s");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::seconds(1), P->Interval);
|
||||
P = parseCachePruningPolicy("prune_interval=2m");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::minutes(2), P->Interval);
|
||||
P = parseCachePruningPolicy("prune_interval=3h");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::hours(3), P->Interval);
|
||||
}
|
||||
|
||||
TEST(CachePruningPolicyParser, Expiration) {
|
||||
auto P = parseCachePruningPolicy("prune_after=1s");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
|
||||
}
|
||||
|
||||
TEST(CachePruningPolicyParser, PercentageOfAvailableSpace) {
|
||||
auto P = parseCachePruningPolicy("cache_size=100%");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(100u, P->PercentageOfAvailableSpace);
|
||||
}
|
||||
|
||||
TEST(CachePruningPolicyParser, Multiple) {
|
||||
auto P = parseCachePruningPolicy("prune_after=1s:cache_size=50%");
|
||||
ASSERT_TRUE(bool(P));
|
||||
EXPECT_EQ(std::chrono::seconds(1200), P->Interval);
|
||||
EXPECT_EQ(std::chrono::seconds(1), P->Expiration);
|
||||
EXPECT_EQ(50u, P->PercentageOfAvailableSpace);
|
||||
}
|
||||
|
||||
TEST(CachePruningPolicyParser, Errors) {
|
||||
EXPECT_EQ("Duration must not be empty",
|
||||
toString(parseCachePruningPolicy("prune_interval=").takeError()));
|
||||
EXPECT_EQ("'foo' not an integer",
|
||||
toString(parseCachePruningPolicy("prune_interval=foos").takeError()));
|
||||
EXPECT_EQ("'24x' must end with one of 's', 'm' or 'h'",
|
||||
toString(parseCachePruningPolicy("prune_interval=24x").takeError()));
|
||||
EXPECT_EQ("'foo' must be a percentage",
|
||||
toString(parseCachePruningPolicy("cache_size=foo").takeError()));
|
||||
EXPECT_EQ("'foo' not an integer",
|
||||
toString(parseCachePruningPolicy("cache_size=foo%").takeError()));
|
||||
EXPECT_EQ("'101' must be between 0 and 100",
|
||||
toString(parseCachePruningPolicy("cache_size=101%").takeError()));
|
||||
EXPECT_EQ("Unknown key: 'foo'",
|
||||
toString(parseCachePruningPolicy("foo=bar").takeError()));
|
||||
}
|
Loading…
Reference in New Issue
Block a user