Preliminary usage graph

This commit is contained in:
Andrea Mazzoleni 2016-01-26 23:25:01 +01:00
parent 3e2420489a
commit 846c02e2c1
7 changed files with 217 additions and 45 deletions

View file

@ -608,7 +608,7 @@ static void printl(const char* str, size_t pad)
len = strlen(str);
while (len < pad) {
printf(" ");
putchar(' ');
++len;
}
}

View file

@ -225,8 +225,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
struct snapraid_disk* disk;
unsigned diskcur;
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* get the next task */
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
@ -284,8 +284,8 @@ static int state_dry_process(struct snapraid_state* state, struct snapraid_parit
countsize += read_size;
}
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* read the parity */
for (l = 0; l < state->level; ++l) {

View file

@ -31,6 +31,11 @@
/****************************************************************************/
/* snapraid */
/**
* Number of measures of the operation progress.
*/
#define PROGRESS_MAX 100
/**
* Max UUID length.
*/
@ -328,10 +333,12 @@ struct snapraid_disk {
char uuid[UUID_MAX]; /**< UUID of the disk. */
uint64_t device; /**< Device identifier. */
uint64_t tick; /**< Usage time of the disk. */
block_off_t total_blocks; /**< Number of total blocks. */
block_off_t free_blocks; /**< Number of free blocks at the last sync. */
uint64_t tick; /**< Usage time. */
uint64_t progress_tick[PROGRESS_MAX]; /**< Last ticks of progress. */
/**
* First free searching block.
* Note that it doesn't necessarily point at the first free block,
@ -423,10 +430,8 @@ struct snapraid_parity {
int skip_access; /**< If the disk is inaccessible and it should be skipped. */
int is_excluded; /**< If the parity is excluded by disk filter. */
/**
* Cumulative time used for parity disks.
*/
uint64_t tick;
uint64_t tick; /**< Usage time. */
uint64_t progress_tick[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
};
/**

View file

@ -364,8 +364,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
/* if not, silent errors are assumed as expected error */
file_is_unsynced = 0;
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* get the next task */
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
@ -456,6 +456,9 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
}
/* until now is hash */
state_usage_hash(state);
if (block_has_updated_hash(block)) {
/* compare the hash */
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
@ -483,8 +486,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
for (; l < LEV_MAX; ++l)
buffer_recov[l] = 0;
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* read the parity */
for (l = 0; l < state->level; ++l) {
@ -563,6 +566,9 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
}
}
}
/* until now is raid */
state_usage_raid(state);
}
if (silent_error_on_this_block || io_error_on_this_block) {
@ -606,8 +612,8 @@ static int state_scrub_process(struct snapraid_state* state, struct snapraid_par
) {
autosavedone = 0; /* restart the counter */
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
state_progress_stop(state);

View file

@ -159,7 +159,9 @@ void state_init(struct snapraid_state* state)
state->parity[l].is_excluded = 0;
}
state->tick_io = 0;
state->tick_cpu = 0;
state->tick_misc = 0;
state->tick_raid = 0;
state->tick_hash = 0;
state->tick_last = tick();
state->share[0] = 0;
state->pool[0] = 0;
@ -3908,6 +3910,8 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
{
time_t now;
int pred;
tommy_node* i;
unsigned l;
now = time(0);
@ -3920,16 +3924,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
if (state->progress_tick == 0
|| state->progress_time[pred] != now
) {
uint64_t tick_total;
uint64_t tick_cpu;
uint64_t tick_total;
time_t elapsed;
unsigned out_perc = 0;
unsigned out_speed = 0;
unsigned out_cpu = 0;
unsigned out_eta = 0;
tick_total = state->tick_cpu + state->tick_io;
tick_cpu = state->tick_cpu;
tick_cpu = state->tick_misc + state->tick_raid + state->tick_hash;
tick_total = tick_cpu + state->tick_io;
elapsed = now - state->progress_whole_start - state->progress_wasted;
/* completion percentage */
@ -3946,8 +3950,10 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
time_t delta_time;
block_off_t delta_pos;
data_off_t delta_size;
uint64_t delta_tick_total;
uint64_t delta_tick_cpu;
uint64_t delta_tick_total;
uint64_t oldest_tick_cpu;
uint64_t oldest_tick_total;
/* number of past measures */
past = state->progress_tick;
@ -3968,11 +3974,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
oldest -= PROGRESS_MAX;
}
oldest_tick_cpu = state->progress_tick_misc[oldest]
+ state->progress_tick_raid[oldest]
+ state->progress_tick_hash[oldest];
oldest_tick_total = oldest_tick_cpu + state->progress_tick_io[oldest];
delta_time = now - state->progress_time[oldest];
delta_pos = countpos - state->progress_pos[oldest];
delta_size = countsize - state->progress_size[oldest];
delta_tick_total = tick_total - state->progress_tick_total[oldest];
delta_tick_cpu = tick_cpu - state->progress_tick_cpu[oldest];
delta_tick_cpu = tick_cpu - oldest_tick_cpu;
delta_tick_total = tick_total - oldest_tick_total;
/* estimate the speed in MB/s */
if (delta_time != 0)
@ -3991,6 +4002,11 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
log_tag("run:pos:%u:%u:%" PRIu64 ":%u:%u:%u:%u:%" PRIu64 "\n", blockpos, countpos, countsize, out_perc, out_eta, out_speed, out_cpu, (uint64_t)elapsed);
log_flush();
} else {
if (msg_level >= MSG_VERBOSE) {
printf("\n\n");
state_usage_graph(state);
}
msg_bar("%u%%, %u MB", out_perc, (unsigned)(countsize / MEGA));
if (out_speed)
msg_bar(", %u MB/s", out_speed);
@ -4005,8 +4021,16 @@ int state_progress(struct snapraid_state* state, block_off_t blockpos, block_off
state->progress_time[state->progress_ptr] = now;
state->progress_pos[state->progress_ptr] = countpos;
state->progress_size[state->progress_ptr] = countsize;
state->progress_tick_cpu[state->progress_ptr] = tick_cpu;
state->progress_tick_total[state->progress_ptr] = tick_total;
state->progress_tick_misc[state->progress_ptr] = state->tick_misc;
state->progress_tick_raid[state->progress_ptr] = state->tick_raid;
state->progress_tick_hash[state->progress_ptr] = state->tick_hash;
state->progress_tick_io[state->progress_ptr] = state->tick_io;
for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data;
disk->progress_tick[state->progress_ptr] = disk->tick;
}
for (l = 0; l < state->level; ++l)
state->parity[l].progress_tick[state->progress_ptr] = state->parity[l].tick;
/* next position */
++state->progress_ptr;
@ -4040,13 +4064,35 @@ void state_usage_waste(struct snapraid_state* state)
state->tick_last = now;
}
void state_usage_cpu(struct snapraid_state* state)
void state_usage_misc(struct snapraid_state* state)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in computations */
state->tick_cpu += delta;
state->tick_misc += delta;
state->tick_last = now;
}
void state_usage_raid(struct snapraid_state* state)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in computations */
state->tick_raid += delta;
state->tick_last = now;
}
void state_usage_hash(struct snapraid_state* state)
{
uint64_t now = tick();
uint64_t delta = now - state->tick_last;
/* increment the time spent in computations */
state->tick_hash += delta;
state->tick_last = now;
}
@ -4085,6 +4131,100 @@ void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, uns
state->tick_last = now;
}
/**
* Print a repeated char.
*/
static void printc(char c, size_t pad)
{
while (pad) {
putchar(c);
--pad;
}
}
/**
* Print a string with space padding.
*/
static void printr(const char* str, size_t pad)
{
size_t len;
len = strlen(str);
while (len < pad) {
putchar(' ');
++len;
}
printf("%s", str);
}
#define USAGE_COLUMN 60
void state_usage_graph(struct snapraid_state* state)
{
uint64_t tick_total;
tommy_node* i;
unsigned l;
size_t pad;
tick_total = state->tick_misc + state->tick_raid + state->tick_hash + state->tick_io;
if (!tick_total)
return;
pad = 4;
for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data;
size_t len = strlen(disk->name);
if (pad < len)
pad = len;
}
for (l = 0; l < state->level; ++l) {
size_t len = strlen(lev_config_name(l));
if (pad < len)
pad = len;
}
/* extra space */
pad += 1;
/* here we don't use msg_progress() because it doesn't allow partial output */
for (i = state->disklist; i != 0; i = i->next) {
struct snapraid_disk* disk = i->data;
printr(disk->name, pad);
printf("%3" PRIu64 "%% | ", disk->tick * 100 / tick_total);
printc('*', disk->tick * USAGE_COLUMN / tick_total);
printf("\n");
}
for (l = 0; l < state->level; ++l) {
printr(lev_config_name(l), pad);
printf("%3" PRIu64 "%% | ", state->parity[l].tick * 100 / tick_total);
printc('*', state->parity[l].tick * USAGE_COLUMN / tick_total);
printf("\n");
}
printr("raid", pad);
printf("%3" PRIu64 "%% | ", state->tick_raid * 100 / tick_total);
printc('*', state->tick_raid * USAGE_COLUMN / tick_total);
printf("\n");
printr("hash", pad);
printf("%3" PRIu64 "%% | ", state->tick_hash * 100 / tick_total);
printc('*', state->tick_hash * USAGE_COLUMN / tick_total);
printf("\n");
printr("misc", pad);
printf("%3" PRIu64 "%% | ", state->tick_misc * 100 / tick_total);
printc('*', state->tick_misc * USAGE_COLUMN / tick_total);
printf("\n");
printr("", pad);
printf(" +-");
printc('-', USAGE_COLUMN);
printf("\n");
}
void state_usage_print(struct snapraid_state* state)
{
uint64_t tick_total;

View file

@ -119,11 +119,6 @@ struct snapraid_option {
int auto_conf; /**< Allow to run without configuration file. */
};
/**
* Number of measures of the operation progress.
*/
#define PROGRESS_MAX 100
struct snapraid_state {
struct snapraid_option opt; /**< Setup options. */
int filter_hidden; /**< Filter out hidden files. */
@ -158,7 +153,9 @@ struct snapraid_state {
/**
* Cumulative time used for computations.
*/
uint64_t tick_cpu;
uint64_t tick_misc;
uint64_t tick_raid;
uint64_t tick_hash;
/**
* Cumulative time used for all io operations of disks.
@ -179,8 +176,10 @@ struct snapraid_state {
time_t progress_time[PROGRESS_MAX]; /**< Last times of progress. */
block_off_t progress_pos[PROGRESS_MAX]; /**< Last positions of progress. */
data_off_t progress_size[PROGRESS_MAX]; /**< Last sizes of progress. */
uint64_t progress_tick_cpu[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
uint64_t progress_tick_total[PROGRESS_MAX]; /**< Last total ticks of progress. */
uint64_t progress_tick_misc[PROGRESS_MAX]; /**< Last cpu ticks of progress. */
uint64_t progress_tick_raid[PROGRESS_MAX]; /**< Last raid ticks of progress. */
uint64_t progress_tick_hash[PROGRESS_MAX]; /**< Last hash ticks of progress. */
uint64_t progress_tick_io[PROGRESS_MAX]; /**< Last io ticks of progress. */
int progress_ptr; /**< Pointer to the next position to fill. Rolling over. */
int progress_tick; /**< Number of measures done. */
@ -340,7 +339,9 @@ void state_usage_waste(struct snapraid_state* state);
/**
* Set the usage time for CPU.
*/
void state_usage_cpu(struct snapraid_state* state);
void state_usage_misc(struct snapraid_state* state);
void state_usage_raid(struct snapraid_state* state);
void state_usage_hash(struct snapraid_state* state);
/**
* Set the usage time for a set of data disks.
@ -357,6 +358,11 @@ void state_usage_parity(struct snapraid_state* state, unsigned* waiting_map, uns
*/
void state_usage_print(struct snapraid_state* state);
/**
* Print a graph of usage time.
*/
void state_usage_graph(struct snapraid_state* state);
/**
* Check the file-system on all disks.
* On error it aborts.

View file

@ -124,8 +124,8 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
/* if we have to use the old hash */
rehash = info_get_rehash(info);
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* if the file is different than the current one, close it */
if (handle[j].file != 0 && handle[j].file != file) {
@ -255,6 +255,9 @@ static int state_hash_process(struct snapraid_state* state, block_off_t blocksta
memhash(state->hash, state->hashseed, hash, buffer, read_size);
}
/* until now is hash */
state_usage_hash(state);
if (block_state == BLOCK_STATE_REP) {
/* compare the hash */
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
@ -817,8 +820,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
block_off_t file_pos;
unsigned diskcur;
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
task = io_data_read(&io, &diskcur, waiting_map, &waiting_mac);
@ -917,6 +920,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
memhash(state->hash, state->hashseed, hash, buffer[diskcur], read_size);
}
/* until now is hash */
state_usage_hash(state);
if (block_has_updated_hash(block)) {
/* compare the hash */
if (memcmp(hash, block->hash, HASH_SIZE) != 0) {
@ -1035,8 +1041,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* if we have something to recover and enough parity */
if (something_to_recover && j == failed_count) {
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
/* read the parity */
/* we are sure that parity exists because */
@ -1082,6 +1088,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* only 'fix' supports the most advanced fixing */
raid_rec(failed_mac, failed_map, diskmax, state->level, state->block_size, buffer);
/* until now is raid */
state_usage_raid(state);
/* check the result and prepare the data */
for (j = 0; j < failed_count; ++j) {
unsigned char hash[HASH_SIZE];
@ -1099,6 +1108,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
memhash(state->hash, state->hashseed, hash, block_buffer, size);
}
/* until now is hash */
state_usage_hash(state);
/* if the hash doesn't match */
if (memcmp(hash, failed[j].block->hash, HASH_SIZE) != 0) {
/* we have not recovered */
@ -1132,6 +1144,9 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* compute the parity */
raid_gen(diskmax, state->level, state->block_size, buffer);
/* until now is raid */
state_usage_raid(state);
/* mark that the parity is going to be written */
parity_going_to_be_updated = 1;
}
@ -1196,7 +1211,7 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
/* Note that the calls to io_parity_write() are mandatory */
/* even if the parity doesn't need to be updated */
/* This because we want to keep track of the time usage */
state_usage_cpu(state);
state_usage_misc(state);
/* write the parity */
for (l = 0; l < state->level; ++l) {
@ -1258,8 +1273,8 @@ static int state_sync_process(struct snapraid_state* state, struct snapraid_pari
) {
autosavedone = 0; /* restart the counter */
/* until now is CPU */
state_usage_cpu(state);
/* until now is misc */
state_usage_misc(state);
state_progress_stop(state);