611 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			611 lines
		
	
	
		
			20 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /**
 | |
|  * Copyright (c) 2021 OceanBase
 | |
|  * OceanBase CE is licensed under Mulan PubL v2.
 | |
|  * You can use this software according to the terms and conditions of the Mulan PubL v2.
 | |
|  * You may obtain a copy of Mulan PubL v2 at:
 | |
|  *          http://license.coscl.org.cn/MulanPubL-2.0
 | |
|  * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 | |
|  * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 | |
|  * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 | |
|  * See the Mulan PubL v2 for more details.
 | |
|  */
 | |
| 
 | |
| #include <stdlib.h>
 | |
| #include <getopt.h>
 | |
| #include "share/ob_version.h"
 | |
| #include "lib/file/file_directory_utils.h"
 | |
| #include "ob_storage_perf_thread.h"
 | |
| #include "lib/stat/ob_diagnose_info.h"
 | |
| #include "share/ob_srv_rpc_proxy.h"
 | |
| #include "share/ob_tenant_mgr.h"
 | |
| #include <gtest/gtest.h>
 | |
| 
 | |
| using namespace oceanbase;
 | |
| using namespace oceanbase::common;
 | |
| using namespace oceanbase::storageperf;
 | |
| using namespace oceanbase::sql;
 | |
| using namespace oceanbase::obsys;
 | |
| 
 | |
| 
 | |
| 
 | |
| #define MPRINT(format, ...) fprintf(stderr, format "\n", ##__VA_ARGS__)
 | |
| #define MPRINTx(format, ...) MPRINT(format, ##__VA_ARGS__); exit(1)
 | |
| 
 | |
| ObArray<int64_t> read_cols;
 | |
| const char *schema_file = "./storage_perf_cost.schema";
 | |
| const char *u_schema = "./storage_perf_update.schema";
 | |
| ObStoragePerfConfig config;
 | |
| 
 | |
| struct ObOptions
 | |
| {
 | |
|   const char *optstr_;
 | |
|   const char *config_file_;
 | |
|   int8_t log_level_;
 | |
| };
 | |
| 
 | |
| static void print_help()
 | |
| {
 | |
|   MPRINT("observer [OPTIONS]");
 | |
|   MPRINT("  -h,--help                print this help");
 | |
|   MPRINT("  -o,--optstr OPTSTR      extra options string");
 | |
|   MPRINT("  -f,--config_file        config_file");
 | |
|   MPRINT("  -l,--log_level LOG_LEVEL server log level");
 | |
| }
 | |
| 
 | |
| static void print_version()
 | |
| {
 | |
|   MPRINT("ob_storage_test (%s %s)", PACKAGE_STRING, RELEASEID);
 | |
|   MPRINT("REVISION: %s", build_version());
 | |
|   MPRINT("BUILD_TIME: %s %s", build_date(), build_time());
 | |
|   MPRINT("BUILD_FLAGS: %s\n", build_flags());
 | |
|   MPRINT("Copyright (c) 2007-2015 Alipay Inc.");
 | |
| }
 | |
| 
 | |
| 
 | |
| static void print_args(int argc, char *argv[])
 | |
| {
 | |
|   for (int i = 0; i < argc - 1; ++i) {
 | |
|     fprintf(stderr, "%s ", argv[i]);
 | |
|   }
 | |
|   fprintf(stderr, "%s\n", argv[argc - 1]);
 | |
| }
 | |
| 
 | |
| static void get_opts_setting(struct option long_opts[],
 | |
|                              char short_opts[],
 | |
|                              const size_t size)
 | |
| {
 | |
|   static struct {
 | |
|     const char *long_name_;
 | |
|     char short_name_;
 | |
|     bool has_arg_;
 | |
|   } ob_opts[] = {
 | |
|     {"help", 'h', 0},
 | |
|     {"log_level", 'l', 1},
 | |
|     {"optstr", 'o', 1},
 | |
|     {"version", 'V', 0},
 | |
|     {"config_file", 'f', 1},
 | |
|     {"read_columns", 'c', 1},
 | |
|     {"read_columns_count", 'C', 1},
 | |
|     {"schema_file", 's', 1},
 | |
|     {"update_schema_file", 'u', 1},
 | |
|     {"row_count", 'r', 1},
 | |
|     {"output_row", 'O', 0},
 | |
|     {"perf_stat", 'S', 0},
 | |
|     {"regenerate_sstable", 'R', 0},
 | |
|     {"repeat_times", 'T', 1},
 | |
|     {"print_stat_info", 'I', 0},
 | |
|     {"flush_block_index_cache", 'Q', 0},
 | |
|     {"flush_block_cache", 'W', 0},
 | |
|     {"flush_row_cache", 'E', 0},
 | |
|     {"WARNING", 'A', 1},
 | |
|     {"bind", 'B', 0},
 | |
|     {"test type", 'Y', 1},
 | |
|     {"multiget range", 'U', 1},
 | |
|     {"no unittest mode", 'G', 0},
 | |
|   };
 | |
| 
 | |
|   size_t opts_cnt = sizeof (ob_opts) / sizeof (ob_opts[0]);
 | |
| 
 | |
|   if (opts_cnt >= size) {
 | |
|     MPRINTx("parse option fail: opts array is too small");
 | |
|   }
 | |
| 
 | |
|   int short_idx = 0;
 | |
| 
 | |
|   for (size_t i = 0; i < opts_cnt; ++i) {
 | |
|     long_opts[i].name = ob_opts[i].long_name_;
 | |
|     long_opts[i].has_arg = ob_opts[i].has_arg_;
 | |
|     long_opts[i].flag = NULL;
 | |
|     long_opts[i].val = ob_opts[i].short_name_;
 | |
| 
 | |
|     short_opts[short_idx++] = ob_opts[i].short_name_;
 | |
|     if (ob_opts[i].has_arg_) {
 | |
|       short_opts[short_idx++] = ':';
 | |
|     }
 | |
|   }
 | |
| }
 | |
| 
 | |
| void set_rt_and_bind_cpu()
 | |
| {
 | |
|   cpu_set_t cpu_set;
 | |
|   struct sched_param param;
 | |
|   CPU_ZERO(&cpu_set);
 | |
|   CPU_SET(5, &cpu_set);
 | |
|   if(sched_setaffinity(static_cast<pid_t>(gettid()), sizeof(cpu_set), &cpu_set) == -1) {
 | |
|     perror("sched_setaffinity() error!\n");
 | |
|     exit(1);
 | |
|   }
 | |
|   param.sched_priority = 99;
 | |
|   if(sched_setscheduler(static_cast<pid_t>(gettid()), SCHED_FIFO, ¶m) == -1){
 | |
|     perror("sched_setscheduler() error!\n");
 | |
|     exit(1);
 | |
|   }
 | |
| }
 | |
| 
 | |
| #define STRTOL_ERR(val) ((errno == ERANGE && ((val) == LONG_MAX || (val) == LONG_MIN)))
 | |
| static void parse_short_opt(const int c, const char *value, ObOptions &opts, ObStoragePerfConfig& config)
 | |
| {
 | |
|   switch (c) {
 | |
|      case 'o':
 | |
|       MPRINT("optstr: %s", value);
 | |
|       opts.optstr_ = value;
 | |
|       break;
 | |
|     case 'l':
 | |
|       MPRINT("log level: %s", value);
 | |
|       if (OB_SUCCESS != OB_LOGGER.level_str2int(value, opts.log_level_)) {
 | |
|         MPRINT("malformed log level, candicates are: "
 | |
|                "    ERROR,USER_ERR,WARN,INFO,TRACE,DEBUG");
 | |
|         MPRINT("!! Back to INFO log level.");
 | |
|         opts.log_level_ = 3;
 | |
|       }
 | |
|       break;
 | |
|     case 'V':
 | |
|       print_version();
 | |
|       exit(0);
 | |
|       break;
 | |
|     case 'f':
 | |
|       opts.config_file_ = value;
 | |
|       break;
 | |
|     case 'B':
 | |
|       set_rt_and_bind_cpu();
 | |
|       break;
 | |
|     case 'c':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         int64_t col_id = 0;
 | |
|         char *opt_arg_end = NULL;
 | |
|         col_id = strtol(value, &opt_arg_end, 10);
 | |
|         if (STRTOL_ERR(col_id)) {
 | |
|           MPRINT("invalid col id");
 | |
|         } else {
 | |
|           read_cols.push_back(col_id);
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'A':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         config.log_level_ = value;
 | |
|       }
 | |
|       break;
 | |
|     case 's':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         schema_file = value;
 | |
|       }
 | |
|       break;
 | |
|     case 'u':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         u_schema = value;
 | |
|       }
 | |
|       break;
 | |
|     case 'O':
 | |
|       config.print_row_ = true;
 | |
|       break;
 | |
|     case 'S':
 | |
|       config.test_single_row_speed_ = true;
 | |
|       break;
 | |
|     case 'C':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         int64_t col_count = 0;
 | |
|         char *opt_arg_end = NULL;
 | |
|         col_count = strtol(value, &opt_arg_end, 10);
 | |
|         if (STRTOL_ERR(col_count)) {
 | |
|           MPRINT("invalid col id");
 | |
|         } else {
 | |
|           config.read_columns_count_ = col_count;
 | |
|           for (int64_t i = 0; i < col_count; ++i) {
 | |
|             read_cols.push_back(i);
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'Y':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid test type");
 | |
|       } else {
 | |
|         if ('S' == value[0]) {
 | |
|           config.scan_thread_count_ = 1;
 | |
|           config.multi_get_thread_count_ = 0;
 | |
|           config.single_get_thread_count_ = 0;
 | |
|         } else if ('M' == value[0]) {
 | |
|           config.scan_thread_count_ = 0;
 | |
|           config.multi_get_thread_count_ = 1;
 | |
|           config.single_get_thread_count_ = 0;
 | |
|         } else if ('G' == value[0]) {
 | |
|           config.scan_thread_count_ = 0;
 | |
|           config.multi_get_thread_count_ = 0;
 | |
|           config.single_get_thread_count_ = 1;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'r':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid col id");
 | |
|       } else {
 | |
|         int64_t row_count = 0;
 | |
|         char *opt_arg_end = NULL;
 | |
|         row_count = strtol(value, &opt_arg_end, 10);
 | |
|         if (STRTOL_ERR(row_count)) {
 | |
|           MPRINT("invalid col id");
 | |
|         } else {
 | |
|           config.total_single_row_count_ = row_count;
 | |
|           config.total_multi_row_count_ = row_count;
 | |
|           config.total_scan_row_count_ = row_count;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'T':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid repeat time");
 | |
|       } else {
 | |
|         int64_t repeat_time = 0;
 | |
|         char *opt_arg_end = NULL;
 | |
|         repeat_time = strtol(value, &opt_arg_end, 10);
 | |
|         if (STRTOL_ERR(repeat_time)) {
 | |
|           MPRINT("invalid col id");
 | |
|         } else {
 | |
|           config.scan_run_ = static_cast<int>(repeat_time);
 | |
|           config.single_get_times_ = repeat_time;
 | |
|           config.multi_get_run_ = static_cast<int>(repeat_time);
 | |
| 
 | |
|           config.scan_times_ = 1;
 | |
|           config.multi_get_times_ = 1;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'U':
 | |
|       if (NULL == value) {
 | |
|         MPRINT("invalid repeat time");
 | |
|       } else {
 | |
|         int64_t mg_range = 0;
 | |
|         char *opt_arg_end = NULL;
 | |
|         mg_range = strtol(value, &opt_arg_end, 10);
 | |
|         if (STRTOL_ERR(mg_range)) {
 | |
|           MPRINT("invalid col id");
 | |
|         } else {
 | |
|           config.get_range_ = mg_range;
 | |
|         }
 | |
|       }
 | |
|       break;
 | |
|     case 'R':
 | |
|       config.is_test_write_ = 1;
 | |
|       config.total_partition_num_ = 1;
 | |
|       break;
 | |
|     case 'I':
 | |
|       config.print_perf_stat_ = true;
 | |
|       break;
 | |
|     case 'Q':
 | |
|       config.flush_block_index_cache_ = true;
 | |
|       break;
 | |
|     case 'W':
 | |
|       config.flush_block_cache_ = true;
 | |
|       break;
 | |
|     case 'E':
 | |
|       config.flush_row_cache_ = true;
 | |
|       break;
 | |
|     case 'G':
 | |
|       config.unittest_mode_ = false;
 | |
|       break;
 | |
|     case 'h':
 | |
|     /*
 | |
|      * {"flush_block_index_cache", 'Q', 0},
 | |
|     {"flush_block_cache", 'W', 0},
 | |
|     {"flush_row_cache", 'E', 0},*/
 | |
| 
 | |
|     default:
 | |
|       print_help();
 | |
|       exit(1);
 | |
|   }
 | |
| }
 | |
| 
 | |
| static void parse_opts(int argc, char *argv[], ObOptions &opts, ObStoragePerfConfig& config)
 | |
| {
 | |
|   static const int MAX_OPTS_CNT = 128;
 | |
|   static char short_opts[MAX_OPTS_CNT*2+1];
 | |
|   static struct option long_opts[MAX_OPTS_CNT];
 | |
| 
 | |
|   get_opts_setting(long_opts, short_opts, MAX_OPTS_CNT);
 | |
| 
 | |
|   int long_opts_idx = 0;
 | |
| 
 | |
|   while (1) {
 | |
|     int c = getopt_long(argc, argv, short_opts, long_opts, &long_opts_idx);
 | |
| 
 | |
|     if (c == -1) {  // end
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     parse_short_opt(c, optarg, opts, config);
 | |
|   }
 | |
| }
 | |
| 
 | |
| int run_test() {
 | |
|   int ret = OB_SUCCESS;
 | |
| 
 | |
|   char log_name[OB_MAX_FILE_NAME_LENGTH];
 | |
| 
 | |
|   ObRestoreSchema restore_schema;
 | |
|   ObSchemaGetterGuard *schema_guard = NULL;
 | |
|   MockSchemaService *schema_service = NULL;
 | |
|   if (OB_FAIL(restore_schema.init())) {
 | |
|     STORAGE_LOG(WARN, "fail to init schema service", K(ret));
 | |
|   } else if (OB_FAIL(restore_schema.parse_from_file(schema_file, schema_guard))) {
 | |
|     STORAGE_LOG(WARN, "fail to parse schema from file", K(ret));
 | |
|   } else if(OB_FAIL(FileDirectoryUtils::create_full_path(const_cast<char *>(config.get_perf_root_dir())))){
 | |
|     STORAGE_LOG(WARN, "fail to mkdir", K(config.get_perf_root_dir()));
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else if(OB_FAIL(FileDirectoryUtils::create_full_path(const_cast<char *>(config.get_slog_dir())))){
 | |
|     STORAGE_LOG(WARN, "fail to mkdir", K(config.get_slog_dir()));
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else if(OB_FAIL(FileDirectoryUtils::create_full_path(const_cast<char *>(config.get_sstable_meta_dir())))){
 | |
|     STORAGE_LOG(WARN, "fail to mkdir", K(config.get_sstable_meta_dir()));
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else if(OB_FAIL(FileDirectoryUtils::create_full_path(const_cast<char *>(config.get_sstable_data_dir())))){
 | |
|     STORAGE_LOG(WARN, "fail to mkdir", K(config.get_sstable_data_dir()));
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else if(OB_FAIL(FileDirectoryUtils::create_full_path(const_cast<char *>(config.get_perf_log_dir())))){
 | |
|     STORAGE_LOG(WARN, "fail to mkdir", K(config.get_perf_log_dir()));
 | |
|     ret = OB_ERR_UNEXPECTED;
 | |
|   } else {
 | |
|     int n = snprintf(log_name, OB_MAX_FILE_NAME_LENGTH, "%s/storage_perf.log", config.get_perf_log_dir());
 | |
|     if(n < 0 || n > OB_MAX_FILE_NAME_LENGTH) {
 | |
|       ret = OB_BUF_NOT_ENOUGH;
 | |
|       STORAGE_LOG(WARN, "fail to create log name", K(config.get_perf_root_dir()), K(OB_MAX_FILE_NAME_LENGTH));
 | |
|     } else {
 | |
|       if (NULL == config.log_level_) {
 | |
|         config.log_level_ = "ERROR";
 | |
|       }
 | |
|       OB_LOGGER.set_log_level(config.log_level_);
 | |
|       OB_LOGGER.set_max_file_size(256L * 1024L * 1024L);
 | |
|       OB_LOGGER.set_file_name(log_name, true);
 | |
|     }
 | |
|     schema_service = restore_schema.schema_service_;
 | |
|   }
 | |
| 
 | |
|   if(OB_SUCC(ret)) {
 | |
|     ObAddr self;
 | |
|     oceanbase::rpc::frame::ObReqTransport req_transport(NULL, NULL);
 | |
|     obrpc::ObSrvRpcProxy rpc_proxy;
 | |
|     if(!self.set_ip_addr("127.0.0.1", 8086)){
 | |
|       ret = OB_ERR_UNEXPECTED;
 | |
|       STORAGE_LOG(WARN, "fail to set ipv4");
 | |
|     } else if (OB_SUCCESS != (ret = ObTenantManager::get_instance().init(self, rpc_proxy,
 | |
|                                       &req_transport, &ObServerConfig::get_instance()))){
 | |
|       STORAGE_LOG(WARN, "fail to init tenant manager", K(ret));
 | |
|     } else if (OB_SUCCESS != (ret = ObTenantManager::get_instance().add_tenant(tenant_id))){
 | |
|       STORAGE_LOG(WARN, "fail to add tenant_id", K(ret), K(tenant_id));
 | |
|     } else if (OB_SUCCESS != (ret =  ObTenantManager::get_instance().set_tenant_mem_limit(tenant_id,
 | |
|         config.get_tenant_cache_size() * 1024L * 1024L/2,
 | |
|         config.get_tenant_cache_size() * 1024L * 1024L))) {
 | |
|       STORAGE_LOG(WARN, "fail to set tenant memory", K(ret));
 | |
|     } else  if(OB_FAIL(ObIOManager::get_instance().init(1L * 1024L * 1024L * 1024L))) {
 | |
|       STORAGE_LOG(WARN, "fail to init ObIOMananger", K(ret));
 | |
|     } else if(OB_SUCCESS != (ret = ObKVGlobalCache::get_instance().init())){
 | |
|       STORAGE_LOG(WARN, "fail to init global kv cache", K(ret));
 | |
|     } else {
 | |
|       lib::set_memory_limit(10L * 1024L * 1024L * 1024L);//40GB
 | |
|       lib::ob_set_reserved_memory(1024L * 1024L * 1024L);//1GB
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OB_SUCC(ret)) {
 | |
|     //multi write thread speed test
 | |
|     if(!config.is_test_write()) {
 | |
|       STORAGE_LOG(WARN, "no thread, cannot start write bench");
 | |
|     } else {
 | |
|       const int thread_no = config.get_total_partition_num();//one partiton one write thread
 | |
|       MultiThreadWrite write(thread_no);
 | |
|       if(OB_FAIL(write.init(schema_service, &restore_schema, config))){
 | |
|         STORAGE_LOG(WARN, "fail to init query", K(ret));
 | |
|       } else {
 | |
|         const int64_t begin = ObTimeUtility::current_time();
 | |
|         int64_t pos = 0;
 | |
|         char time_string_buf[max_time_string_length+1];
 | |
|         if (OB_FAIL(ObTimeUtility::usec_format_to_str(begin, bianque_format, &time_string_buf[0], max_time_string_length, pos))) {
 | |
|           STORAGE_LOG(WARN, "failed to convert bianque format string", K(ret));
 | |
|         } else {
 | |
|           time_string_buf[pos] = '\0';
 | |
|           _OB_LOG(ERROR, "write_begin_time: %s", time_string_buf);
 | |
|           write.start();
 | |
|           write.wait();
 | |
|           const int64_t end = ObTimeUtility::current_time();
 | |
|           if (OB_FAIL(write.get_first_error())) {
 | |
|             STORAGE_LOG(WARN, "failed to run write test", K(ret));
 | |
|           } else {
 | |
|             pos = 0;
 | |
|             if (OB_FAIL(ObTimeUtility::usec_format_to_str(end, bianque_format, &time_string_buf[0], max_time_string_length, pos))) {
 | |
|               STORAGE_LOG(WARN, "failed to convert bianque format string", K(ret));
 | |
|             } else {
 | |
|               time_string_buf[pos] = '\0';
 | |
|               _OB_LOG(ERROR, "write_end_time: %s", time_string_buf);
 | |
|               const int64_t duration = end - begin;
 | |
|               const int64_t total_write_size_mb = write.get_total_macro_num() * 2L;
 | |
|               _OB_LOG(ERROR, "total write thread %d , total time %ld us, total size  %ld MB, speed is %.4LF MB/s",
 | |
|                   thread_no, duration, total_write_size_mb, 1000L * 1000L * (total_write_size_mb/static_cast<long double>(duration)));
 | |
|             }
 | |
|           }
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OB_SUCC(ret)) {
 | |
|     //multi thread single get speed test
 | |
|     const int partiton_num = config.get_total_partition_num();
 | |
|     const int thread_no = config.get_single_get_thread_count() * partiton_num;
 | |
|     if(thread_no <= 0) {
 | |
|       STORAGE_LOG(WARN, "no thread, cannot start single get bench");
 | |
|     } else {
 | |
|       MultiThreadSingleGet single_get(thread_no);
 | |
|       if (NULL != u_schema) {
 | |
|         single_get.set_update_schema(u_schema);
 | |
|       }
 | |
|       if(OB_FAIL(single_get.init(schema_service, &restore_schema, config))){
 | |
|         STORAGE_LOG(WARN, "fail to init query", K(ret));
 | |
|       } else {
 | |
|         single_get.assign_read_cols(read_cols);
 | |
|         const int64_t begin = ObTimeUtility::current_time();
 | |
|         single_get.start();
 | |
|         single_get.wait();
 | |
|         const int64_t end = ObTimeUtility::current_time();
 | |
|         if (OB_FAIL(single_get.get_first_error())) {
 | |
|           STORAGE_LOG(WARN, "failed to run single get test", K(ret));
 | |
|         } else {
 | |
|           const int64_t duration = end - begin;
 | |
|           const int64_t total_get_row = thread_no * config.get_total_single_row_count();
 | |
|           _OB_LOG(ERROR, "total single get thread %d , total time %ld us, total single row count %ld speed is %.4LF us/row",
 | |
|               thread_no, duration, total_get_row, duration/static_cast<long double>(total_get_row));
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OB_SUCC(ret)) {
 | |
|     //multi thread multi get speed test
 | |
|     const int partiton_num = config.get_total_partition_num();
 | |
|     int thread_no = config.get_multi_get_thread_count() * partiton_num;
 | |
|     if(thread_no <= 0) {
 | |
|       STORAGE_LOG(WARN, "no thread, cannot start multi get bench");
 | |
|     } else {
 | |
|       MultiThreadMultiGet multi_get(thread_no);
 | |
|       if (NULL != u_schema) {
 | |
|         multi_get.set_update_schema(u_schema);
 | |
|       }
 | |
|       if(OB_FAIL(multi_get.init(schema_service, &restore_schema, config))){
 | |
|         STORAGE_LOG(WARN, "fail to init query", K(ret));
 | |
|       } else {
 | |
|         multi_get.assign_read_cols(read_cols);
 | |
|         const int64_t begin = ObTimeUtility::current_time();
 | |
|         multi_get.start();
 | |
|         multi_get.wait();
 | |
|         const int64_t end = ObTimeUtility::current_time();
 | |
|         if (OB_FAIL(multi_get.get_first_error())) {
 | |
|           STORAGE_LOG(WARN, "failed to run multi get test", K(ret));
 | |
|         } else {
 | |
|           const int64_t duration = end - begin;
 | |
|           const int64_t total_get_row = thread_no * config.get_total_multi_row_count();
 | |
|           _OB_LOG(ERROR, "total multi get thread %d , total time %ld us, total multi row count %ld speed is %.4LF us/row",
 | |
|               thread_no, duration, total_get_row, duration/static_cast<long double>(total_get_row));
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   if (OB_SUCC(ret)) {
 | |
|     //multi thread scan speed test
 | |
|     const int partiton_num = config.get_total_partition_num();
 | |
|     int thread_no = config.get_scan_thread_count() * partiton_num;
 | |
|     if(thread_no <= 0) {
 | |
|       STORAGE_LOG(WARN, "no thread, cannot start scan speed bench");
 | |
|     } else {
 | |
|       MultiThreadScan scan(thread_no);
 | |
|       if (NULL != u_schema) {
 | |
|         scan.set_update_schema(u_schema);
 | |
|       }
 | |
|       if(OB_FAIL(scan.init(schema_service, &restore_schema, config))){
 | |
|         STORAGE_LOG(WARN, "fail to init query", K(ret));
 | |
|       } else {
 | |
|         scan.assign_read_cols(read_cols);
 | |
|         //every thread has different num of row count, no need to cal total speed
 | |
|         scan.start();
 | |
|         scan.wait();
 | |
|         if (OB_FAIL(scan.get_first_error())) {
 | |
|           STORAGE_LOG(WARN, "failed to run scan test", K(ret));
 | |
|         }
 | |
|       }
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //No matter what, we need to release the space occupied
 | |
|   if (config.unittest_mode_) {
 | |
|     ObStoragePerfWrite write;
 | |
|     if(OB_FAIL(write.init(&config, 0, &restore_schema, schema_service))){
 | |
|       STORAGE_LOG(WARN, "fail to init", K(ret));
 | |
|     } else {
 | |
|       write.cleanup_sstable();
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   //global destory
 | |
|   ObIOManager::get_instance().destroy();
 | |
|   ObKVGlobalCache::get_instance().destroy();
 | |
|   ObTenantManager::get_instance().destroy();
 | |
|   return ret;
 | |
| }
 | |
| 
 | |
| TEST(StorageCostModelUtil, func_check) {
 | |
|   int ret = OB_SUCCESS;
 | |
|   //set up unittest mode params
 | |
|   config.is_test_write_ = 1;
 | |
|   config.partition_size_ = 1;
 | |
|   config.total_multi_row_count_ = 10;
 | |
|   config.total_single_row_count_ = 1;
 | |
|   config.total_multi_row_count_ = 100;
 | |
|   config.total_scan_row_count_ = 1000;
 | |
|   config.get_range_ = 1000;
 | |
|   config.scan_run_ = 1;
 | |
|   config.single_get_times_ = 1;
 | |
|   config.multi_get_run_ = 1;
 | |
|   config.scan_times_ = 1;
 | |
|   config.multi_get_times_ = 1;
 | |
|   config.single_get_thread_count_ = 1;
 | |
|   config.multi_get_thread_count_ = 1;
 | |
|   config.scan_thread_count_ = 1;
 | |
|   config.read_columns_count_ = 10;
 | |
|   for (int64_t i = 0; i < config.read_columns_count_; ++i) {
 | |
|     read_cols.push_back(i);
 | |
|   }
 | |
|   ret = run_test();
 | |
|   EXPECT_EQ(ret, OB_SUCCESS);
 | |
| }
 | |
| 
 | |
| int main(int argc, char *argv[])
 | |
| {
 | |
|   int ret = OB_SUCCESS;
 | |
|   print_args(argc, argv);
 | |
|   ObOptions opts;
 | |
|   if(OB_FAIL(config.init("./storage_perf.conf"))){
 | |
|     STORAGE_LOG(WARN, "fail to get config file", K(ret));
 | |
|     exit(1);
 | |
|   }
 | |
|   parse_opts(argc, argv, opts, config);
 | |
|   if (config.unittest_mode_) {
 | |
|     int argc_f = 1;
 | |
|     char arg_f[] = "fake";
 | |
|     char *argv[] = {arg_f};
 | |
|     testing::InitGoogleTest(&argc_f, argv);
 | |
|     return RUN_ALL_TESTS();
 | |
|   } else {
 | |
|     ret = run_test();
 | |
|   }
 | |
|   return 0;
 | |
| }
 | 
