add cold start
This commit is contained in:
@@ -26,6 +26,7 @@
|
|||||||
#define CHUNK_SIZE_STEP_UP 1024 * 1024 * 4 // Increase step: 4MB (symmetric with step down)
|
#define CHUNK_SIZE_STEP_UP 1024 * 1024 * 4 // Increase step: 4MB (symmetric with step down)
|
||||||
#define CHUNK_SIZE_STEP_DOWN 1024 * 1024 * 4 // Decrease step: 4MB (symmetric exploration)
|
#define CHUNK_SIZE_STEP_DOWN 1024 * 1024 * 4 // Decrease step: 4MB (symmetric exploration)
|
||||||
#define CHUNK_MEASURE_INTERVAL 64 // Measure performance every 64 chunks
|
#define CHUNK_MEASURE_INTERVAL 64 // Measure performance every 64 chunks
|
||||||
|
#define WARMUP_MEASUREMENTS 16 // Skip first 16 measurements (cache writes)
|
||||||
|
|
||||||
// Multi-armed bandit exploration parameters
|
// Multi-armed bandit exploration parameters
|
||||||
#define EXPLORATION_EPSILON 0.10 // 10% exploration rate (epsilon-greedy)
|
#define EXPLORATION_EPSILON 0.10 // 10% exploration rate (epsilon-greedy)
|
||||||
@@ -67,6 +68,7 @@ private:
|
|||||||
size_t bestChunkSize;
|
size_t bestChunkSize;
|
||||||
unsigned int chunkCounter;
|
unsigned int chunkCounter;
|
||||||
unsigned int totalChunkCounter; // Total chunks written (for periodic re-exploration)
|
unsigned int totalChunkCounter; // Total chunks written (for periodic re-exploration)
|
||||||
|
unsigned int warmupCounter; // Count warm-up measurements
|
||||||
std::chrono::high_resolution_clock::time_point measurementStartTime;
|
std::chrono::high_resolution_clock::time_point measurementStartTime;
|
||||||
double bestThroughputMBps;
|
double bestThroughputMBps;
|
||||||
double lastThroughputMBps;
|
double lastThroughputMBps;
|
||||||
|
|||||||
+65
-28
@@ -44,6 +44,7 @@ Shred::Shred()
|
|||||||
bestChunkSize = CHUNK_SIZE_START;
|
bestChunkSize = CHUNK_SIZE_START;
|
||||||
chunkCounter = 0;
|
chunkCounter = 0;
|
||||||
totalChunkCounter = 0; // Track total chunks for periodic re-exploration
|
totalChunkCounter = 0; // Track total chunks for periodic re-exploration
|
||||||
|
warmupCounter = 0; // Track warm-up measurements
|
||||||
bestThroughputMBps = 0.0;
|
bestThroughputMBps = 0.0;
|
||||||
lastThroughputMBps = 0.0;
|
lastThroughputMBps = 0.0;
|
||||||
bytesWrittenInMeasurement = 0;
|
bytesWrittenInMeasurement = 0;
|
||||||
@@ -55,9 +56,12 @@ Shred::Shred()
|
|||||||
|
|
||||||
Logger::logThis()->info("Adaptive chunk size optimization ENABLED (Multi-Armed Bandit) - Starting with " +
|
Logger::logThis()->info("Adaptive chunk size optimization ENABLED (Multi-Armed Bandit) - Starting with " +
|
||||||
to_string(currentChunkSize / (1024 * 1024)) + " MB chunks");
|
to_string(currentChunkSize / (1024 * 1024)) + " MB chunks");
|
||||||
Logger::logThis()->info("Exploration strategy: " + to_string((int)(EXPLORATION_EPSILON * 100)) +
|
Logger::logThis()->info("Configuration: min=" + to_string(CHUNK_SIZE_MIN / (1024 * 1024)) +
|
||||||
"% epsilon-greedy + periodic re-exploration every " +
|
"MB, max=" + to_string(CHUNK_SIZE_MAX / (1024 * 1024)) +
|
||||||
to_string(REEXPLORATION_INTERVAL) + " chunks");
|
"MB, step=" + to_string(CHUNK_SIZE_STEP_UP / (1024 * 1024)) + "MB");
|
||||||
|
Logger::logThis()->info("Exploration: " + to_string((int)(EXPLORATION_EPSILON * 100)) +
|
||||||
|
"% epsilon-greedy + periodic every " + to_string(REEXPLORATION_INTERVAL) + " chunks");
|
||||||
|
Logger::logThis()->info("Warm-up: First " + to_string(WARMUP_MEASUREMENTS) + " measurements ignored (cold start protection)");
|
||||||
}
|
}
|
||||||
|
|
||||||
Shred::~Shred()
|
Shred::~Shred()
|
||||||
@@ -102,31 +106,48 @@ void Shred::evaluateThroughput(Drive *drive)
|
|||||||
double throughputMBps = (bytesWrittenInMeasurement / (1024.0 * 1024.0)) / elapsedSeconds;
|
double throughputMBps = (bytesWrittenInMeasurement / (1024.0 * 1024.0)) / elapsedSeconds;
|
||||||
lastThroughputMBps = throughputMBps;
|
lastThroughputMBps = throughputMBps;
|
||||||
|
|
||||||
Logger::logThis()->info("Throughput measurement - ChunkSize: " +
|
// Warm-up period - ignore first measurements
|
||||||
to_string(currentChunkSize / (1024 * 1024)) + " MB, " +
|
warmupCounter++;
|
||||||
"Throughput: " + to_string((int)throughputMBps) + " MB/s, " +
|
bool isWarmup = (warmupCounter <= WARMUP_MEASUREMENTS);
|
||||||
"Best: " + to_string((int)bestThroughputMBps) + " MB/s" +
|
|
||||||
" - Drive: " + drive->getSerial());
|
|
||||||
|
|
||||||
// Check if this is better than our best
|
if (isWarmup)
|
||||||
if (throughputMBps > bestThroughputMBps)
|
|
||||||
{
|
{
|
||||||
bestThroughputMBps = throughputMBps;
|
Logger::logThis()->info("WARM-UP #" + to_string(warmupCounter) + "/" + to_string(WARMUP_MEASUREMENTS) +
|
||||||
bestChunkSize = currentChunkSize;
|
" - ChunkSize: " + to_string(currentChunkSize / (1024 * 1024)) + " MB, " +
|
||||||
throughputIncreasing = true;
|
"Throughput: " + to_string((int)throughputMBps) + " MB/s (not used for optimization)" +
|
||||||
|
" - Drive: " + drive->getSerial());
|
||||||
Logger::logThis()->info("NEW BEST throughput: " + to_string((int)bestThroughputMBps) +
|
|
||||||
" MB/s with " + to_string(currentChunkSize / (1024 * 1024)) +
|
|
||||||
" MB chunks - Drive: " + drive->getSerial());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
throughputIncreasing = false;
|
Logger::logThis()->info("Throughput measurement - ChunkSize: " +
|
||||||
|
to_string(currentChunkSize / (1024 * 1024)) + " MB, " +
|
||||||
|
"Throughput: " + to_string((int)throughputMBps) + " MB/s, " +
|
||||||
|
"Best: " + to_string((int)bestThroughputMBps) + " MB/s" +
|
||||||
|
" - Drive: " + drive->getSerial());
|
||||||
|
|
||||||
|
// Check if this is better than our best (only after warm-up)
|
||||||
|
if (throughputMBps > bestThroughputMBps)
|
||||||
|
{
|
||||||
|
bestThroughputMBps = throughputMBps;
|
||||||
|
bestChunkSize = currentChunkSize;
|
||||||
|
throughputIncreasing = true;
|
||||||
|
|
||||||
|
Logger::logThis()->info("NEW BEST throughput: " + to_string((int)bestThroughputMBps) +
|
||||||
|
" MB/s with " + to_string(currentChunkSize / (1024 * 1024)) +
|
||||||
|
" MB chunks - Drive: " + drive->getSerial());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
throughputIncreasing = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust chunk size for next measurement interval
|
// Adjust chunk size for next measurement interval (skip during warm-up)
|
||||||
adjustChunkSize(drive);
|
if (warmupCounter > WARMUP_MEASUREMENTS)
|
||||||
|
{
|
||||||
|
adjustChunkSize(drive);
|
||||||
|
}
|
||||||
|
|
||||||
// Start new measurement
|
// Start new measurement
|
||||||
startMeasurement();
|
startMeasurement();
|
||||||
@@ -158,12 +179,12 @@ void Shred::performExploration(Drive *drive)
|
|||||||
{
|
{
|
||||||
size_t savedChunkSize = currentChunkSize;
|
size_t savedChunkSize = currentChunkSize;
|
||||||
|
|
||||||
// Generate random chunk size between MIN and MAX (aligned to 4MB boundaries)
|
// Generate random chunk size between MIN and MAX (aligned to STEP boundaries)
|
||||||
size_t numSteps = (CHUNK_SIZE_MAX - CHUNK_SIZE_MIN) / CHUNK_SIZE_STEP_UP;
|
size_t numSteps = (CHUNK_SIZE_MAX - CHUNK_SIZE_MIN) / CHUNK_SIZE_STEP_UP;
|
||||||
size_t randomStep = rand() % (numSteps + 1);
|
size_t randomStep = rand() % (numSteps + 1);
|
||||||
explorationChunkSize = CHUNK_SIZE_MIN + (randomStep * CHUNK_SIZE_STEP_UP);
|
explorationChunkSize = CHUNK_SIZE_MIN + (randomStep * CHUNK_SIZE_STEP_UP);
|
||||||
|
|
||||||
// Clamp to valid range
|
// Clamp to valid range (safety check)
|
||||||
if (explorationChunkSize < CHUNK_SIZE_MIN)
|
if (explorationChunkSize < CHUNK_SIZE_MIN)
|
||||||
explorationChunkSize = CHUNK_SIZE_MIN;
|
explorationChunkSize = CHUNK_SIZE_MIN;
|
||||||
if (explorationChunkSize > CHUNK_SIZE_MAX)
|
if (explorationChunkSize > CHUNK_SIZE_MAX)
|
||||||
@@ -173,10 +194,12 @@ void Shred::performExploration(Drive *drive)
|
|||||||
explorationMode = true;
|
explorationMode = true;
|
||||||
currentChunkSize = explorationChunkSize;
|
currentChunkSize = explorationChunkSize;
|
||||||
|
|
||||||
|
// Enhanced logging with debug info
|
||||||
Logger::logThis()->info("EXPLORATION MODE: Testing " +
|
Logger::logThis()->info("EXPLORATION MODE: Testing " +
|
||||||
to_string(explorationChunkSize / (1024 * 1024)) + " MB chunks " +
|
to_string(explorationChunkSize / (1024 * 1024)) + " MB chunks " +
|
||||||
"(was " + to_string(savedChunkSize / (1024 * 1024)) + " MB, best: " +
|
"(randomStep=" + to_string(randomStep) + "/" + to_string(numSteps) + ", " +
|
||||||
to_string(bestChunkSize / (1024 * 1024)) + " MB)" +
|
"was " + to_string(savedChunkSize / (1024 * 1024)) + " MB, " +
|
||||||
|
"best: " + to_string(bestChunkSize / (1024 * 1024)) + " MB)" +
|
||||||
" - Drive: " + drive->getSerial());
|
" - Drive: " + drive->getSerial());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,10 +223,22 @@ void Shred::adjustChunkSize(Drive *drive)
|
|||||||
if (explorationMode)
|
if (explorationMode)
|
||||||
{
|
{
|
||||||
explorationMode = false;
|
explorationMode = false;
|
||||||
currentChunkSize = bestChunkSize; // Return to best known chunk size
|
|
||||||
Logger::logThis()->info("EXPLORATION ENDED - Returning to best known: " +
|
// CRITICAL: Return to best known chunk size, not current
|
||||||
to_string(bestChunkSize / (1024 * 1024)) + " MB" +
|
if (currentChunkSize != bestChunkSize)
|
||||||
" - Drive: " + drive->getSerial());
|
{
|
||||||
|
currentChunkSize = bestChunkSize;
|
||||||
|
Logger::logThis()->info("EXPLORATION ENDED - Returning to best known: " +
|
||||||
|
to_string(bestChunkSize / (1024 * 1024)) + " MB" +
|
||||||
|
" (exploration tested " + to_string(oldChunkSize / (1024 * 1024)) + " MB)" +
|
||||||
|
" - Drive: " + drive->getSerial());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::logThis()->info("EXPLORATION ENDED - Staying at current best: " +
|
||||||
|
to_string(bestChunkSize / (1024 * 1024)) + " MB" +
|
||||||
|
" - Drive: " + drive->getSerial());
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,6 +271,7 @@ void Shred::adjustChunkSize(Drive *drive)
|
|||||||
currentChunkSize = CHUNK_SIZE_MIN;
|
currentChunkSize = CHUNK_SIZE_MIN;
|
||||||
Logger::logThis()->info("Reached minimum chunk size: " +
|
Logger::logThis()->info("Reached minimum chunk size: " +
|
||||||
to_string(currentChunkSize / (1024 * 1024)) + " MB" +
|
to_string(currentChunkSize / (1024 * 1024)) + " MB" +
|
||||||
|
" (best remains: " + to_string(bestChunkSize / (1024 * 1024)) + " MB)" +
|
||||||
" - Drive: " + drive->getSerial());
|
" - Drive: " + drive->getSerial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,6 +281,7 @@ void Shred::adjustChunkSize(Drive *drive)
|
|||||||
Logger::logThis()->info("Adjusted chunk size: " +
|
Logger::logThis()->info("Adjusted chunk size: " +
|
||||||
to_string(oldChunkSize / (1024 * 1024)) + " MB -> " +
|
to_string(oldChunkSize / (1024 * 1024)) + " MB -> " +
|
||||||
to_string(currentChunkSize / (1024 * 1024)) + " MB" +
|
to_string(currentChunkSize / (1024 * 1024)) + " MB" +
|
||||||
|
" (best: " + to_string(bestChunkSize / (1024 * 1024)) + " MB)" +
|
||||||
" - Drive: " + drive->getSerial());
|
" - Drive: " + drive->getSerial());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user