332 lines
11 KiB
C
332 lines
11 KiB
C
/*
|
|
* Copyright (c) 2020 YuQing <384681@qq.com>
|
|
*
|
|
* This program is free software: you can use, redistribute, and/or modify
|
|
* it under the terms of the Lesser GNU General Public License, version 3
|
|
* or later ("LGPL"), as published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but WITHOUT
|
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
* FITNESS FOR A PARTICULAR PURPOSE.
|
|
*
|
|
* You should have received a copy of the Lesser GNU General Public License
|
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <math.h>
|
|
#include <time.h>
|
|
#include <inttypes.h>
|
|
#include <sys/types.h>
|
|
#include <sys/time.h>
|
|
#include <sys/stat.h>
|
|
#include "fastcommon/logger.h"
|
|
#include "fastcommon/fast_buffer.h"
|
|
#include "fastcommon/sched_thread.h"
|
|
|
|
typedef enum {
|
|
TEST_TYPE_NONE = 0,
|
|
TEST_TYPE_ITOA,
|
|
TEST_TYPE_FTOA,
|
|
TEST_TYPE_INT2HEX,
|
|
TEST_TYPE_APPEND
|
|
} TestType;
|
|
|
|
typedef enum {
|
|
DA_SLICE_TYPE_FILE = 'F', /* in file slice */
|
|
DA_SLICE_TYPE_CACHE = 'C', /* in memory cache */
|
|
DA_SLICE_TYPE_ALLOC = 'A' /* allocate slice (index and space allocate only) */
|
|
} DASliceType;
|
|
|
|
typedef struct {
|
|
int64_t version;
|
|
uint64_t trunk_id; //0 for not inited
|
|
uint32_t length; //data length
|
|
uint32_t offset; //space offset
|
|
uint32_t size; //space size
|
|
} DAPieceFieldStorage;
|
|
|
|
typedef struct {
|
|
int64_t version; //for stable sort only
|
|
uint64_t oid; //object ID
|
|
uint64_t fid; //field ID (key)
|
|
uint32_t extra; //such as slice offset
|
|
char op_type;
|
|
DASliceType slice_type;
|
|
DAPieceFieldStorage storage;
|
|
} DATrunkSpaceLogRecord;
|
|
|
|
static inline void log_pack_by_append(const DATrunkSpaceLogRecord
|
|
*record, FastBuffer *buffer, const bool have_extra_field)
|
|
{
|
|
fast_buffer_append_int64(buffer, (uint32_t)g_current_time);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->storage.version);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->oid);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->fid);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_char(buffer, record->op_type);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->storage.trunk_id);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->storage.length);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->storage.offset);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_int64(buffer, record->storage.size);
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_char(buffer, record->slice_type);
|
|
|
|
if (have_extra_field) {
|
|
fast_buffer_append_char(buffer, ' ');
|
|
fast_buffer_append_char(buffer, record->extra);
|
|
fast_buffer_append_char(buffer, '\n');
|
|
} else {
|
|
fast_buffer_append_char(buffer, '\n');
|
|
}
|
|
}
|
|
|
|
static inline void log_pack_by_sprintf(const DATrunkSpaceLogRecord
|
|
*record, FastBuffer *buffer, const bool have_extra_field)
|
|
{
|
|
buffer->length += sprintf(buffer->data + buffer->length,
|
|
"%u %"PRId64" %"PRId64" %"PRId64" %c %"PRId64" %u %u %u %c",
|
|
(uint32_t)g_current_time, record->storage.version,
|
|
record->oid, record->fid, record->op_type,
|
|
record->storage.trunk_id, record->storage.length,
|
|
record->storage.offset, record->storage.size,
|
|
record->slice_type);
|
|
if (have_extra_field) {
|
|
buffer->length += sprintf(buffer->data + buffer->length,
|
|
" %u\n", record->extra);
|
|
} else {
|
|
*(buffer->data + buffer->length++) = '\n';
|
|
}
|
|
}
|
|
|
|
#define BINLOG_FILENAME_PREFIX_STR "binlog."
|
|
#define BINLOG_FILENAME_PREFIX_LEN (sizeof(BINLOG_FILENAME_PREFIX_STR) - 1)
|
|
|
|
static inline int cache_binlog_filename_by_sprintf(
|
|
const char *data_path, const char *subdir_name,
|
|
const uint32_t subdirs, const uint64_t id,
|
|
char *full_filename, const int size)
|
|
{
|
|
int path_index;
|
|
path_index = id % subdirs;
|
|
return sprintf(full_filename, "%s/%s/%02X/%02X/%s%08"PRIX64,
|
|
data_path, subdir_name, path_index, path_index,
|
|
BINLOG_FILENAME_PREFIX_STR, id);
|
|
}
|
|
|
|
static inline int cache_binlog_filename_by_append(
|
|
const char *data_path, const char *subdir_name,
|
|
const uint32_t subdirs, const uint64_t id,
|
|
char *full_filename, const int size)
|
|
{
|
|
int path_index;
|
|
int path_len;
|
|
int subdir_len;
|
|
char *p;
|
|
|
|
path_index = id % subdirs;
|
|
path_len = strlen(data_path);
|
|
subdir_len = strlen(subdir_name);
|
|
p = full_filename;
|
|
memcpy(p, data_path, path_len);
|
|
p += path_len;
|
|
*p++ = '/';
|
|
memcpy(p, subdir_name, subdir_len);
|
|
p += subdir_len;
|
|
*p++ = '/';
|
|
*p++ = g_upper_hex_chars[(path_index >> 4) & 0x0F];
|
|
*p++ = g_upper_hex_chars[path_index & 0x0F];
|
|
*p++ = '/';
|
|
*p++ = g_upper_hex_chars[(path_index >> 4) & 0x0F];
|
|
*p++ = g_upper_hex_chars[path_index & 0x0F];
|
|
*p++ = '/';
|
|
memcpy(p, BINLOG_FILENAME_PREFIX_STR, BINLOG_FILENAME_PREFIX_LEN);
|
|
p += BINLOG_FILENAME_PREFIX_LEN;
|
|
if (id <= UINT32_MAX) {
|
|
p += int2HEX(id, p, 8);
|
|
} else {
|
|
p += long2HEX(id, p, 8);
|
|
}
|
|
|
|
return p - full_filename;
|
|
}
|
|
|
|
static void usage(const char *program)
|
|
{
|
|
fprintf(stderr, "Usage: %s [-t {itoa | ftoa | int2hex | append | all}]\n",
|
|
program);
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
const bool binary_mode = true;
|
|
const bool check_capacity = false;
|
|
const bool have_extra_field = false;
|
|
const int LOOP = 10 * 1000 * 1000;
|
|
const char *data_path = "/opt/fastcfs/fdir/data";
|
|
const char *subdir_name = "binlog";
|
|
const uint32_t subdirs = 256;
|
|
|
|
int result;
|
|
TestType test_type = TEST_TYPE_ITOA;
|
|
TestType type_start;
|
|
TestType type_last;
|
|
uint64_t id = 123456;
|
|
double d = 123.456;
|
|
int ch;
|
|
int i;
|
|
int len;
|
|
int64_t start_time_us;
|
|
int convert_time_us;
|
|
int sprintf_time_us;
|
|
double ratio;
|
|
FastBuffer buffer;
|
|
DATrunkSpaceLogRecord record;
|
|
char full_filename1[PATH_MAX];
|
|
char full_filename2[PATH_MAX];
|
|
char buff[32] = {0};
|
|
char *caption;
|
|
|
|
log_init();
|
|
g_current_time = time(NULL);
|
|
if ((result=fast_buffer_init_ex(&buffer, 256,
|
|
binary_mode, check_capacity)) != 0)
|
|
{
|
|
return result;
|
|
}
|
|
|
|
type_start = type_last = TEST_TYPE_ITOA;
|
|
while ((ch=getopt(argc, argv, "ht:")) != -1) {
|
|
switch (ch) {
|
|
case 'h':
|
|
usage(argv[0]);
|
|
return 0;
|
|
case 't':
|
|
if (strcasecmp(optarg, "itoa") == 0) {
|
|
type_start = type_last = TEST_TYPE_ITOA;
|
|
} else if (strcasecmp(optarg, "ftoa") == 0) {
|
|
type_start = type_last = TEST_TYPE_FTOA;
|
|
} else if (strcasecmp(optarg, "int2hex") == 0) {
|
|
type_start = type_last = TEST_TYPE_INT2HEX;
|
|
} else if (strcasecmp(optarg, "append") == 0) {
|
|
type_start = type_last = TEST_TYPE_APPEND;
|
|
} else if (strcasecmp(optarg, "all") == 0) {
|
|
type_start = TEST_TYPE_ITOA;
|
|
type_last = TEST_TYPE_APPEND;
|
|
} else {
|
|
fprintf(stderr, "invalid type: %s\n", optarg);
|
|
return EINVAL;
|
|
}
|
|
break;
|
|
default:
|
|
usage(argv[0]);
|
|
return EINVAL;
|
|
}
|
|
}
|
|
|
|
for (test_type=type_start; test_type<=type_last; test_type++) {
|
|
if (test_type == TEST_TYPE_APPEND) {
|
|
memset(&record, 0, sizeof(record));
|
|
record.op_type = 'C';
|
|
record.slice_type = DA_SLICE_TYPE_FILE;
|
|
record.storage.version = 1111;
|
|
record.oid = 9007211709265131LL;
|
|
record.fid = 0;
|
|
record.storage.trunk_id = 61;
|
|
record.storage.length = 62;
|
|
record.storage.offset = 12345;
|
|
record.storage.size = 64;
|
|
}
|
|
|
|
start_time_us = get_current_time_us();
|
|
for (i=0; i<LOOP; i++) {
|
|
switch (test_type) {
|
|
case TEST_TYPE_APPEND:
|
|
cache_binlog_filename_by_sprintf(data_path, subdir_name,
|
|
subdirs, ++id, full_filename1, sizeof(full_filename1));
|
|
fast_buffer_reset(&buffer);
|
|
log_pack_by_sprintf(&record, &buffer, have_extra_field);
|
|
break;
|
|
case TEST_TYPE_ITOA:
|
|
sprintf(buff, "%"PRId64, id);
|
|
break;
|
|
case TEST_TYPE_FTOA:
|
|
sprintf(buff, "%.2f", d);
|
|
break;
|
|
case TEST_TYPE_INT2HEX:
|
|
sprintf(buff, "%x", (int)id);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
sprintf_time_us = (get_current_time_us() - start_time_us);
|
|
|
|
start_time_us = get_current_time_us();
|
|
for (i=0; i<LOOP; i++) {
|
|
switch (test_type) {
|
|
case TEST_TYPE_APPEND:
|
|
cache_binlog_filename_by_append(data_path, subdir_name,
|
|
subdirs, ++id, full_filename2, sizeof(full_filename2));
|
|
fast_buffer_reset(&buffer);
|
|
log_pack_by_append(&record, &buffer, have_extra_field);
|
|
break;
|
|
case TEST_TYPE_ITOA:
|
|
len = fc_itoa(id, buff);
|
|
*(buff + len) = '\0';
|
|
break;
|
|
case TEST_TYPE_FTOA:
|
|
len = fc_ftoa(d, 2, buff);
|
|
*(buff + len) = '\0';
|
|
break;
|
|
case TEST_TYPE_INT2HEX:
|
|
int2hex(id, buff, 0);
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
convert_time_us = (get_current_time_us() - start_time_us);
|
|
|
|
if (convert_time_us > 0) {
|
|
ratio = (double)sprintf_time_us / (double)convert_time_us;
|
|
} else {
|
|
ratio = 1.0;
|
|
}
|
|
|
|
switch (test_type) {
|
|
case TEST_TYPE_ITOA:
|
|
caption = "itoa";
|
|
break;
|
|
case TEST_TYPE_FTOA:
|
|
caption = "ftoa";
|
|
break;
|
|
case TEST_TYPE_INT2HEX:
|
|
caption = "int2hex";
|
|
break;
|
|
case TEST_TYPE_APPEND:
|
|
caption = "append";
|
|
break;
|
|
default:
|
|
caption = "unkown";
|
|
break;
|
|
}
|
|
printf("sprintf time: %d ms, %s time: %d ms, "
|
|
"sprintf time / %s time: %d%%\n",
|
|
sprintf_time_us / 1000, caption, convert_time_us / 1000,
|
|
caption, (int)(ratio * 100.00));
|
|
}
|
|
|
|
fast_buffer_destroy(&buffer);
|
|
return 0;
|
|
}
|