Skip to content

Commit

Permalink
Merge pull request #172 from malin1993ml/master
Browse files Browse the repository at this point in the history
Prime offset of anti-cache with timestamps
  • Loading branch information
apavlo committed Aug 30, 2014
2 parents 359a42d + ae0a358 commit 87d7f76
Show file tree
Hide file tree
Showing 14 changed files with 150 additions and 27 deletions.
1 change: 1 addition & 0 deletions build-common.xml
Expand Up @@ -156,6 +156,7 @@
<arg value="site.anticache_batching=${site.anticache_batching}" />
<arg value="site.anticache_dbtype=${site.anticache_dbtype}" />
<arg value="site.anticache_timestamps=${site.anticache_timestamps}" />
<arg value="site.anticache_timestamps_prime=${site.anticache_timestamps_prime}" />
<arg value="site.storage_mmap=${site.storage_mmap}" />
<arg value="site.storage_mmap_dir=${site.storage_mmap_dir}" />
<arg value="site.storage_mmap_file_size=${site.storage_mmap_file_size}" />
Expand Down
3 changes: 3 additions & 0 deletions build.py
Expand Up @@ -406,6 +406,9 @@
if CTX.ANTICACHE_TIMESTAMPS:
CTX.CPPFLAGS += " -DANTICACHE_TIMESTAMPS"

if CTX.ANTICACHE_TIMESTAMPS_PRIME:
CTX.CPPFLAGS += " -DANTICACHE_TIMESTAMPS_PRIME"

# Bring in berkeleydb library
CTX.SYSTEM_DIRS.append(os.path.join(CTX.OUTPUT_PREFIX, 'berkeleydb'))
CTX.THIRD_PARTY_STATIC_LIBS.extend([
Expand Down
5 changes: 3 additions & 2 deletions build.xml
Expand Up @@ -886,8 +886,9 @@ NATIVE EE STUFF
<arg value="ANTICACHE_ENABLE=${site.anticache_enable}" />
<arg value="ANTICACHE_BUILD=${site.anticache_build}" />
<arg value="ANTICACHE_REVERSIBLE_LRU=${site.anticache_reversible_lru}" />
<arg value="ANTICACHE_NVM=${site.anticache_nvm}" />
<arg value="ANTICACHE_TIMESTAMPS=${site.anticache_timestamps}" />
<arg value="ANTICACHE_NVM=${site.anticache_nvm}" />
<arg value="ANTICACHE_TIMESTAMPS=${site.anticache_timestamps}" />
<arg value="ANTICACHE_TIMESTAMPS_PRIME=${site.anticache_timestamps_prime}" />
<arg value="${build}" />
</exec>
</target>
Expand Down
5 changes: 5 additions & 0 deletions buildtools.py
Expand Up @@ -47,6 +47,7 @@ def __init__(self, args):
self.ANTICACHE_DRAM = False
self.ARIES= False
self.ANTICACHE_TIMESTAMPS = True
self.ANTICACHE_TIMESTAMPS_PRIME = True

for arg in [x.strip().upper() for x in args]:
if arg in ["DEBUG", "RELEASE", "MEMCHECK", "MEMCHECK_NOFREELIST"]:
Expand Down Expand Up @@ -90,6 +91,10 @@ def __init__(self, args):
parts = arg.split("=")
if len(parts) > 1 and not parts[1].startswith("${"):
self.ANTICACHE_TIMESTAMPS = bool(parts[1])
if arg.startswith("ANTICACHE_TIMESTAMPS_PRIME="):
parts = arg.split("=")
if len(parts) > 1 and not parts[1].startswith("${"):
self.ANTICACHE_TIMESTAMPS_PRIME = bool(parts[1])

if arg.startswith("LOG_LEVEL="):
parts = arg.split("=")
Expand Down
10 changes: 5 additions & 5 deletions scripts/timestamps/ycsb.sh
Expand Up @@ -35,10 +35,10 @@ BASE_PROJECT="ycsb"
BASE_DIR=`pwd`
OUTPUT_DIR="~/data/ycsb/read-heavy/2/80-20"

for skew in 1.2; do
for skew in 0.8 1.01 1.1 1.2; do
for round in 1 2 3; do
OUTPUT_PREFIX="ycsb-T500-NoLoop/$round-ycsb1G-timestamps-T500-S$skew"
LOG_PREFIX="logs/ycsb-T500-NoLoop/$round-ycsb1G-timestamps-T500-S$skew"
OUTPUT_PREFIX="test/ycsb-T500-NoLoop/$round-ycsb1G-flru-T500-S$skew"
LOG_PREFIX="logs/test/ycsb-T500-NoLoop/$round-ycsb1G-flru-T500-S$skew"
echo $OUTPUT_PREFIX
sed -i '$ d' "properties/benchmarks/ycsb.properties"
echo "skew_factor = $skew" >> "properties/benchmarks/ycsb.properties"
Expand Down Expand Up @@ -66,7 +66,7 @@ for skew in 1.2; do
"-Dsite.cpu_affinity_one_partition_per_core=true" \
#"-Dsite.cpu_partition_blacklist=0,2,4,6,8,10,12,14,16,18" \
#"-Dsite.cpu_utility_blacklist=0,2,4,6,8,10,12,14,16,18" \
"-Dsite.network_incoming_limit_txns=60000" \
"-Dsite.network_incoming_limit_txns=50000" \
"-Dsite.commandlog_enable=false" \
"-Dsite.txn_incoming_delay=5" \
"-Dsite.exec_postprocessing_threads=false" \
Expand All @@ -81,7 +81,7 @@ for skew in 1.2; do
# Client Params
"-Dclient.scalefactor=10" \
"-Dclient.memory=2048" \
"-Dclient.txnrate=4000" \
"-Dclient.txnrate=3500" \
"-Dclient.warmup=120000" \
"-Dclient.duration=300000" \
"-Dclient.interval=5000" \
Expand Down
4 changes: 4 additions & 0 deletions src/ee/anticache/EvictedTable.cpp
Expand Up @@ -33,6 +33,10 @@ EvictedTable::EvictedTable(ExecutorContext *ctx) : PersistentTable(ctx, false) {

}

#ifdef ANTICACHE_TIMESTAMPS_PRIME
enum { prime_size = 25 };
static const int prime_list[prime_size] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
#endif

/*
Insert a tuple into the evicted table but don't create any UNDO action. Return the address
Expand Down
110 changes: 93 additions & 17 deletions src/ee/anticache/EvictionIterator.cpp
Expand Up @@ -51,7 +51,15 @@
#define RANDOM_SCALE 4

namespace voltdb {


#ifdef ANTICACHE_TIMESTAMPS_PRIME
/**
* if we use a prime-offset sampling strategy, here are the prime numbers we want to choose from:
* Notice that those numbers are sufficient, because their product is bigger than block size.
*/
const int EvictionIterator::prime_list[prime_size] = {2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97};
#endif

EvictionIterator::EvictionIterator(Table *t)
{
//ptable = static_cast<PersistentTable*>(table);
Expand All @@ -73,9 +81,12 @@ void EvictionIterator::reserve(int64_t amount) {
int tuple_size = ptable->m_schema->tupleLength() + TUPLE_HEADER_SIZE;
int active_tuple = (int)ptable->activeTupleCount();
int evict_num = 0;
//uint32_t tuples_per_block = ptable->m_tuplesPerBlock;
int64_t used_tuple = ptable->usedTupleCount();
#ifdef ANTICACHE_TIMESTAMPS_PRIME
uint32_t tuples_per_block = ptable->m_tuplesPerBlock;
#endif

if (active_tuple)
if (active_tuple)
evict_num = (int)(amount / (tuple_size + ptable->nonInlinedMemorySize() / active_tuple));
else
evict_num = (int)(amount / tuple_size);
Expand All @@ -85,38 +96,108 @@ void EvictionIterator::reserve(int64_t amount) {
if (evict_num > active_tuple)
evict_num = active_tuple;

// TODO: there's another block-sample strategy, but it does not get good accuracy of selecting cold data.
// If we use that, the throughput of VOTER can increases from 55,000 to 59,000, but IO of other experiments increases a lot
// The reason why this is slow? I guess is the rand() and % operation
//
// Lin Ma
int pick_num = evict_num * RANDOM_SCALE;

int block_num = (int)ptable->m_data.size();
int block_size = ptable->m_tuplesPerBlock;
int location_size;
#ifndef ANTICACHE_TIMESTAMPS_PRIME
int block_location;
#endif

srand((unsigned int)time(0));

VOLT_INFO("evict pick num: %d %d\n", evict_num, pick_num);
VOLT_INFO("active_tuple: %d\n", active_tuple);
VOLT_INFO("block number: %d\n", block_num);

int activeN = 0, evictedN = 0;
m_size = 0;
current_tuple_id = 0;

#ifdef ANTICACHE_TIMESTAMPS_PRIME
int pick_num_block = (int)(((int64_t)pick_num * tuples_per_block) / used_tuple);
int last_full_block = (int)(used_tuple / block_size);
VOLT_INFO("LOG: %d %d %ld\n", last_full_block, tuples_per_block, used_tuple);
int last_block_size = (int)(used_tuple % block_size);
int pick_num_last_block = pick_num - pick_num_block * last_full_block;
#endif

// If we'll evict the entire table, we should do a scan instead of sampling.
// The main reason we should do that is to past the test...
if (evict_num < active_tuple) {
candidates = new EvictionTuple[pick_num];
#ifdef ANTICACHE_TIMESTAMPS_PRIME
for (int i = 0; i < last_full_block; ++i) {

/**
* if this is a beginning of a loop of scan, find a proper step to let it sample tuples from almost the whole block
* TODO: Here we use a method that every time try a different prime number from what we use last time. Is it better?
* That would need further analysis.
*/
if (ptable->m_stepPrime[i] < 0) {
int ideal_step = (rand() % 5) * tuples_per_block / pick_num_block;
int old_prime = - ptable->m_stepPrime[i];
for (int j = prime_size - 1; j >= 0; --j) {
if (prime_list[j] != old_prime && (tuples_per_block % prime_list[j]) > 0) {
ptable->m_stepPrime[i] = prime_list[j];
VOLT_TRACE("DEBUG: %d %d\n", tuples_per_block, ptable->m_stepPrime[i]);
}
if (prime_list[j] <= ideal_step)
break;
}
VOLT_INFO("Prime of block %d: %d %d\n", i, tuples_per_block, ptable->m_stepPrime[i]);
}

// now scan the block with a step of we select.
// if we go across the boundry, minus it back to the beginning (like a mod operation)
int step_prime = ptable->m_stepPrime[i];
int step_offset = step_prime * tuple_size;
int block_size_bytes = block_size * tuple_size;
addr = ptable->m_data[i] + ptable->m_evictPosition[i];
uint64_t end_of_block = (uint64_t)ptable->m_data[i] + block_size_bytes;
bool flag_new = false;
for (int j = 0; j < pick_num_block; ++j) {
VOLT_TRACE("Flip addr: %p %p %lu\n", addr, ptable->m_data[i], ((uint64_t)addr - (uint64_t)ptable->m_data[i]) / 1024);

current_tuple->move(addr);

if (current_tuple->isActive()) {
candidates[m_size].setTuple(current_tuple->getTimeStamp(), addr);
m_size++;
}

addr += step_offset;
if ((uint64_t)addr >= end_of_block)
addr -= block_size_bytes;
if (addr == ptable->m_data[i])
flag_new = true;
}
int new_position = (int)((uint64_t)addr - (uint64_t)ptable->m_data[i]);
ptable->m_evictPosition[i] = new_position;
if (flag_new)
ptable->m_stepPrime[i] = - ptable->m_stepPrime[i];
}
if (last_full_block < block_num) {
addr = ptable->m_data[last_full_block];
char* current_addr;
for (int j = 0; j < pick_num_last_block; ++j) {
current_addr = addr + (rand() % last_block_size) * tuple_size;
current_tuple->move(current_addr);
if (!current_tuple->isActive() || current_tuple->isEvicted())
continue;

candidates[m_size].setTuple(current_tuple->getTimeStamp(), current_addr);
m_size++;
}
}

#else
for (int i = 0; i < pick_num; i++) {
// should we use a faster random generator?
block_location = rand() % block_num;
addr = ptable->m_data[block_location];
if ((block_location + 1) * block_size > ptable->usedTupleCount())
location_size = (int)(ptable->usedTupleCount() - block_location * block_size);
if ((block_location + 1) * block_size > used_tuple)
location_size = (int)(used_tuple - block_location * block_size);
else
location_size = block_size;
addr += (rand() % location_size) * tuple_size;
Expand All @@ -125,15 +206,13 @@ void EvictionIterator::reserve(int64_t amount) {

VOLT_DEBUG("Flip addr: %p\n", addr);

if (current_tuple->isActive()) activeN++;
if (current_tuple->isEvicted()) evictedN++;

if (!current_tuple->isActive() || current_tuple->isEvicted())
continue;

candidates[m_size].setTuple(current_tuple->getTimeStamp(), addr);
m_size++;
}
#endif
} else {
candidates = new EvictionTuple[active_tuple];
for (int i = 0; i < block_num; ++i) {
Expand All @@ -145,9 +224,6 @@ void EvictionIterator::reserve(int64_t amount) {
for (int j = 0; j < location_size; j++) {
current_tuple->move(addr);

if (current_tuple->isActive()) activeN++;
if (current_tuple->isEvicted()) evictedN++;

if (!current_tuple->isActive() || current_tuple->isEvicted()) {
addr += tuple_size;
continue;
Expand Down
6 changes: 6 additions & 0 deletions src/ee/anticache/EvictionIterator.h
Expand Up @@ -94,6 +94,12 @@ class EvictionIterator : public TupleIterator
EvictionTuple *candidates;
int32_t m_size;
#endif

#ifdef ANTICACHE_TIMESTAMPS_PRIME
enum { prime_size = 25 };
static const int prime_list[prime_size];
#endif

};

}
Expand Down
2 changes: 1 addition & 1 deletion src/ee/common/tabletuple.h
Expand Up @@ -79,7 +79,7 @@ namespace voltdb {
| flags (1 byte) | "previous" tuple id (4 bytes) | "next" tuple id (4 bytes) | tuple data |
---------------------------------------------------------------------------------------------------
(d). Anti-Caching with time stamps
(d). Anti-Caching with timestamps
----------------------------------------------------------
| flags (1 byte) | time stamp (4 bytes) | tuple data |
----------------------------------------------------------
Expand Down
4 changes: 4 additions & 0 deletions src/ee/storage/persistenttable.h
Expand Up @@ -434,6 +434,10 @@ inline void PersistentTable::allocateNextBlock() {
#endif
char *memory = (char*)(new char[bytes]);
m_data.push_back(memory);
#ifdef ANTICACHE_TIMESTAMPS_PRIME
m_evictPosition.push_back(0);
m_stepPrime.push_back(-1);
#endif
#ifdef MEMCHECK_NOFREELIST
assert(m_allocatedTuplePointers.insert(memory).second);
m_deletedTuplePointers.erase(memory);
Expand Down
13 changes: 13 additions & 0 deletions src/ee/storage/table.h
Expand Up @@ -411,6 +411,15 @@ class Table {
int64_t m_bytesRead;
#endif

#ifdef ANTICACHE_TIMESTAMPS_PRIME
// track the position of where we're eviction so far
std::vector<int> m_evictPosition;

// which prime we use as the step
std::vector<int> m_stepPrime;
#endif


#ifdef MEMCHECK_NOFREELIST
int64_t m_deletedTupleCount;
//Store pointers to all allocated tuples so they can be freed on destruction
Expand Down Expand Up @@ -499,6 +508,10 @@ inline void Table::allocateNextBlock() {
#endif
char *memory = (char*)(new char[bytes]);
m_data.push_back(memory);
#ifdef ANTICACHE_TIMESTAMPS_PRIME
m_evictPosition.push_back(0);
m_stepPrime.push_back(-1);
#endif
#ifdef MEMCHECK_NOFREELIST
assert(m_allocatedTuplePointers.insert(memory).second);
m_deletedTuplePointers.erase(memory);
Expand Down
2 changes: 1 addition & 1 deletion src/frontend/edu/brown/hstore/AntiCacheManager.java
Expand Up @@ -448,7 +448,7 @@ protected boolean checkEviction() {

/**
* TODO: What commented in the loop below will make the eviction manager ignore index memory while calculating eviction threshold
* In some cases, we may do want exclude index memory. Then uncomment them.
* In some cases, we may do want exclude index memory. Then uncomment them!
*/
for (PartitionStats stats : this.partitionStats) {
totalSizeKb += stats.sizeKb;// - stats.indexes;
Expand Down
2 changes: 2 additions & 0 deletions src/frontend/edu/brown/hstore/PartitionExecutor.java
Expand Up @@ -1205,6 +1205,8 @@ else if (hstore_conf.site.specexec_enable) {
if (this.utilityWork()) {
nextWork = UTIL_WORK_MSG;
}
} else {
ThreadUtil.sleep(5);
}
} // WHILE
} catch (final Throwable ex) {
Expand Down
10 changes: 9 additions & 1 deletion src/frontend/edu/brown/hstore/conf/HStoreConf.java
Expand Up @@ -720,12 +720,20 @@ public final class SiteConf extends Conf {
public String anticache_dbtype;
@ConfigProperty(
description="Enable the anti-cache timestamps feature. This requires that the system " +
"is compiled with ${site.anticache_timestamps} set to true.",
"is compiled with ${site.anticache_enable} set to true.",
defaultBoolean=true,
experimental=true
)
public boolean anticache_timestamps;

@ConfigProperty(
description="Enable the anti-cache timestamps use a prime sample strategy instead of radom-tuple sampling." +
"This is compiled with ${site.anticache_timestamps} set to true.",
defaultBoolean=true,
experimental=true
)
public boolean anticache_timestamps_prime;

// ----------------------------------------------------------------------------
// Storage MMAP Options
// ----------------------------------------------------------------------------
Expand Down

0 comments on commit 87d7f76

Please sign in to comment.