// currently, this method checks if there if a file already exists, and if so, assumes it is valid. // ideally, a check should be made to ensure the saved SSD state matches with the state of the current global parameters void Experiment::calibrate_and_save(Workload_Definition* workload, string name, int num_IOs, bool force) { //string file_name = base_folder + "calibrated_state.txt"; string file_name = base_folder + name; std::ifstream ifile(file_name.c_str()); if (ifile && !force) { return; // file exists } StatisticsGatherer::set_record_statistics(false); //StatisticsGatherer::get_global_instance()->init(); Thread::set_record_internal_statistics(false); VisualTracer::init(); //Free_Space_Meter::init(); //Free_Space_Per_LUN_Meter::init(); printf("Creating calibrated SSD state.\n"); OperatingSystem* os = new OperatingSystem(); os->set_num_writes_to_stop_after(num_IOs); vector<Thread*> init_threads = workload->generate_instance(); os->set_threads(init_threads); os->set_progress_meter_granularity(1000); os->run(); os->get_ssd()->execute_all_remaining_events(); save_state(os, file_name); //StatisticsGatherer::get_global_instance()->print(); //Free_Space_Meter::print(); //Free_Space_Per_LUN_Meter::print(); delete os; }
Experiment_Result Experiment::copyback_map_experiment(vector<Thread*> (*experiment)(int highest_lba), int cb_map_min, int cb_map_max, int cb_map_inc, int used_space, string data_folder, string name, int IO_limit) { Experiment_Result experiment_result(name, data_folder, "", "Max copyback map size"); experiment_result.start_experiment(); const int num_pages = NUMBER_OF_ADDRESSABLE_BLOCKS() * BLOCK_SIZE; for (int copyback_map_size = cb_map_min; copyback_map_size <= cb_map_max; copyback_map_size += cb_map_inc) { int highest_lba = (int) ((double) num_pages * used_space / 100); printf("-------------------------------------------------------\n"); printf("Experiment with %d copybacks allowed in copyback map. \n", copyback_map_size); printf("-------------------------------------------------------\n"); MAX_ITEMS_IN_COPY_BACK_MAP = copyback_map_size; // Run experiment vector<Thread*> threads = experiment(highest_lba); OperatingSystem* os = new OperatingSystem(); os->set_threads(threads); os->set_num_writes_to_stop_after(IO_limit); os->run(); // Collect statistics from this experiment iteration (save in csv files) experiment_result.collect_stats(copyback_map_size); StatisticsGatherer::get_global_instance()->print(); if (PRINT_LEVEL >= 1) { StateVisualiser::print_page_status(); StateVisualiser::print_block_ages(); } delete os; } experiment_result.end_experiment(); return experiment_result; }
Experiment_Result Experiment::copyback_experiment(vector<Thread*> (*experiment)(int highest_lba), int used_space, int max_copybacks, string data_folder, string name, int IO_limit) { Experiment_Result experiment_result(name, data_folder, "", "CopyBacks allowed before ECC check"); experiment_result.start_experiment(); const int num_pages = NUMBER_OF_ADDRESSABLE_BLOCKS() * BLOCK_SIZE; for (int copybacks_allowed = 0; copybacks_allowed <= max_copybacks; copybacks_allowed += 1) { int highest_lba = (int) ((double) num_pages * used_space / 100); printf("---------------------------------------\n"); printf("Experiment with %d copybacks allowed.\n", copybacks_allowed); printf("---------------------------------------\n"); MAX_REPEATED_COPY_BACKS_ALLOWED = copybacks_allowed; // Run experiment vector<Thread*> threads = experiment(highest_lba); OperatingSystem* os = new OperatingSystem(); os->set_threads(threads); os->set_num_writes_to_stop_after(IO_limit); os->run(); // Collect statistics from this experiment iteration (save in csv files) experiment_result.collect_stats(copybacks_allowed); StatisticsGatherer::get_global_instance()->print(); if (PRINT_LEVEL >= 1) { StateVisualiser::print_page_status(); StateVisualiser::print_block_ages(); } delete os; } experiment_result.end_experiment(); return experiment_result; }
void Experiment::simple_experiment_double(string name, T* var, T min, T max, T inc) { string data_folder = base_folder + name + "/"; mkdir(data_folder.c_str(), 0755); Experiment_Result global_result(name, data_folder, "Global/", variable_name); global_result.start_experiment(); T& variable = *var; for (variable = min; variable <= max; variable += inc) { printf("----------------------------------------------------------------------------------------------------------\n"); printf("%s : %s \n", name.c_str(), to_string(variable).c_str()); printf("----------------------------------------------------------------------------------------------------------\n"); string point_folder_name = data_folder + to_string(variable) + "/"; mkdir(point_folder_name.c_str(), 0755); if (generate_trace_file) { VisualTracer::init(data_folder); } else { VisualTracer::init(); } write_config_file(point_folder_name); Queue_Length_Statistics::init(); Free_Space_Meter::init(); Free_Space_Per_LUN_Meter::init(); OperatingSystem* os; if (calibrate_for_each_point && calibration_workload != NULL) { string calib_file_name = "calib-" + to_string(variable) + ".txt"; Experiment::calibrate_and_save(calibration_workload, calib_file_name); os = load_state(calib_file_name); } else if (!calibration_file.empty()) { os = load_state(calibration_file); } else { os = new OperatingSystem(); } if (workload != NULL) { vector<Thread*> experiment_threads = workload->generate_instance(); os->set_threads(experiment_threads); } os->set_num_writes_to_stop_after(io_limit); os->run(); StatisticsGatherer::get_global_instance()->print(); Utilization_Meter::print(); Queue_Length_Statistics::print_avg(); Free_Space_Meter::print(); Free_Space_Per_LUN_Meter::print(); global_result.collect_stats(variable, StatisticsGatherer::get_global_instance()); write_results_file(point_folder_name); delete os; } global_result.end_experiment(); vector<Experiment_Result> result; result.push_back(global_result); results.push_back(result); }
void Experiment::run_single_point(string name) { string data_folder = base_folder + name + "/"; mkdir(data_folder.c_str(), 0755); StatisticsGatherer::set_record_statistics(true); Thread::set_record_internal_statistics(true); Experiment_Result global_result(name, data_folder, "Global/", ""); Individual_Threads_Statistics::init(); global_result.start_experiment(); Free_Space_Meter::init(); Free_Space_Per_LUN_Meter::init(); if (generate_trace_file) { VisualTracer::init(data_folder); } else { VisualTracer::init(); } write_config_file(data_folder); Queue_Length_Statistics::init(); OperatingSystem* os = calibration_file.empty() ? new OperatingSystem() : load_state(calibration_file); os->set_progress_meter_granularity(20); if (workload != NULL) { vector<Thread*> experiment_threads = workload->generate_instance(); os->set_threads(experiment_threads); } os->set_num_writes_to_stop_after(io_limit); os->run(); StatisticsGatherer::get_global_instance()->print(); StatisticsGatherer::get_global_instance()->print_mapping_info(); //StatisticsGatherer::get_global_instance()->print_gc_info(); Utilization_Meter::print(); //Individual_Threads_Statistics::print(); //Queue_Length_Statistics::print_distribution(); //Queue_Length_Statistics::print_avg(); Free_Space_Meter::print(); Free_Space_Per_LUN_Meter::print(); global_result.collect_stats(0, StatisticsGatherer::get_global_instance()); write_results_file(data_folder); if (!alternate_location_for_results_file.compare("") == 0) { printf("writing results in %s\n", alternate_location_for_results_file.c_str()); write_results_file(alternate_location_for_results_file); } global_result.end_experiment(); vector<Experiment_Result> result; result.push_back(global_result); results.push_back(result); delete os; }
OperatingSystem* Experiment::load_state(string name) { string file_name = base_folder + name; printf("loading calibration file: %s\n", file_name.c_str()); std::ifstream file(file_name.c_str()); boost::archive::text_iarchive ia(file); ia.register_type<FtlImpl_Page>( ); ia.register_type<Block_manager_parallel>(); ia.register_type<Sequential_Locality_BM>( ); ia.register_type<File_Manager>( ); ia.register_type<Simple_Thread>( ); ia.register_type<Random_IO_Pattern>( ); ia.register_type<Sequential_IO_Pattern>( ); ia.register_type<WRITES>( ); ia.register_type<TRIMS>( ); ia.register_type<READS>( ); ia.register_type<READS_OR_WRITES>(); ia.register_type<Asynchronous_Random_Writer>(); ia.register_type<Asynchronous_Random_Reader>(); ia.register_type<MTRand>(); ia.register_type<MTRand_closed>(); ia.register_type<MTRand_open>(); ia.register_type<MTRand53>(); OperatingSystem* os; ia >> os; vector<Thread*> threads; ia >> threads; Individual_Threads_Statistics::init(); for (auto t : threads) { //Individual_Threads_Statistics::register_thread(t, ""); } os->set_threads(threads); //os->init_threads(); IOScheduler* scheduler = os->get_ssd()->get_scheduler(); scheduler->init(); Block_manager_parent* bm = Block_manager_parent::get_new_instance(); bm->copy_state(scheduler->get_bm()); delete scheduler->get_bm(); scheduler->set_block_manager(bm); Migrator* m = scheduler->get_migrator(); m->set_block_manager(bm); Garbage_Collector* gc = m->get_garbage_collector(); gc->set_block_manager(bm); return os; }
vector<Experiment_Result> Experiment::random_writes_on_the_side_experiment(Workload_Definition* workload, int write_threads_min, int write_threads_max, int write_threads_inc, string name, int IO_limit, double used_space, int random_writes_min_lba, int random_writes_max_lba) { string data_folder = base_folder + name; mkdir(data_folder.c_str(), 0755); Experiment_Result global_result (name, data_folder, "Global/", "Number of concurrent random write threads"); Experiment_Result experiment_result (name, data_folder, "Experiment_Threads/", "Number of concurrent random write threads"); Experiment_Result write_threads_result(name, data_folder, "Noise_Threads/", "Number of concurrent random write threads"); global_result.start_experiment(); experiment_result.start_experiment(); write_threads_result.start_experiment(); for (int random_write_threads = write_threads_min; random_write_threads <= write_threads_max; random_write_threads += write_threads_inc) { printf("----------------------------------------------------------------------------------------------------------\n"); printf("%s : Experiment with max %d concurrent random writes threads.\n", name.c_str(), random_write_threads); printf("----------------------------------------------------------------------------------------------------------\n"); StatisticsGatherer* experiment_statistics_gatherer = new StatisticsGatherer(); StatisticsGatherer* random_writes_statics_gatherer = new StatisticsGatherer(); Thread* initial_write = new Asynchronous_Sequential_Writer(0, used_space); if (workload != NULL) { vector<Thread*> experiment_threads = workload->generate_instance(); unify_under_one_statistics_gatherer(experiment_threads, experiment_statistics_gatherer); initial_write->add_follow_up_threads(experiment_threads); } for (int i = 0; i < random_write_threads; i++) { ulong randseed = (i*3)+537; Simple_Thread* random_writes = new Synchronous_Random_Writer(random_writes_min_lba, random_writes_max_lba, randseed); Simple_Thread* random_reads = new Synchronous_Random_Reader(random_writes_min_lba, random_writes_max_lba, randseed+461); /*if (workload == NULL) { random_writes->set_experiment_thread(true); random_reads->set_experiment_thread(true); }*/ random_writes->set_num_ios(INFINITE); random_reads->set_num_ios(INFINITE); random_writes->set_statistics_gatherer(random_writes_statics_gatherer); random_reads->set_statistics_gatherer(random_writes_statics_gatherer); initial_write->add_follow_up_thread(random_writes); initial_write->add_follow_up_thread(random_reads); } vector<Thread*> threads; threads.push_back(initial_write); OperatingSystem* os = new OperatingSystem(); os->set_threads(threads); os->set_num_writes_to_stop_after(IO_limit); os->run(); // Collect statistics from this experiment iteration (save in csv files) global_result.collect_stats (random_write_threads, StatisticsGatherer::get_global_instance()); experiment_result.collect_stats (random_write_threads, experiment_statistics_gatherer); write_threads_result.collect_stats(random_write_threads, random_writes_statics_gatherer); if (workload == NULL) { StatisticsGatherer::get_global_instance()->print(); } else { experiment_statistics_gatherer->print(); } //StatisticsGatherer::get_global_instance()->print(); //random_writes_statics_gatherer->print(); if (PRINT_LEVEL >= 1) { StateVisualiser::print_page_status(); StateVisualiser::print_block_ages(); } delete os; delete experiment_statistics_gatherer; delete random_writes_statics_gatherer; } global_result.end_experiment(); experiment_result.end_experiment(); write_threads_result.end_experiment(); vector<Experiment_Result> results; results.push_back(global_result); results.push_back(experiment_result); results.push_back(write_threads_result); if (workload != NULL) delete workload; return results; }