fast_buffer support options: binary_mode and check_capacity
parent
558670bc63
commit
e4898affdd
|
|
@ -64,6 +64,7 @@ src/tests/test_thread_local
|
||||||
src/tests/test_memcpy
|
src/tests/test_memcpy
|
||||||
src/tests/mblock_benchmark
|
src/tests/mblock_benchmark
|
||||||
src/tests/cpool_benchmark
|
src/tests/cpool_benchmark
|
||||||
|
src/tests/test_fast_buffer
|
||||||
|
|
||||||
# other
|
# other
|
||||||
*.swp
|
*.swp
|
||||||
|
|
|
||||||
|
|
@ -26,23 +26,28 @@
|
||||||
#include "fc_memory.h"
|
#include "fc_memory.h"
|
||||||
#include "fast_buffer.h"
|
#include "fast_buffer.h"
|
||||||
|
|
||||||
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity)
|
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity,
|
||||||
|
const bool binary_mode, const bool check_capacity)
|
||||||
{
|
{
|
||||||
buffer->length = 0;
|
buffer->length = 0;
|
||||||
|
buffer->binary_mode = binary_mode;
|
||||||
if (init_capacity > 0)
|
if (init_capacity > 0)
|
||||||
{
|
{
|
||||||
buffer->alloc_size = init_capacity;
|
buffer->alloc_size = init_capacity;
|
||||||
|
buffer->check_capacity = check_capacity;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
buffer->alloc_size = 256;
|
buffer->alloc_size = 256;
|
||||||
|
buffer->check_capacity = true;
|
||||||
}
|
}
|
||||||
buffer->data = (char *)fc_malloc(buffer->alloc_size);
|
buffer->data = (char *)fc_malloc(buffer->alloc_size);
|
||||||
if (buffer->data == NULL)
|
if (buffer->data == NULL)
|
||||||
{
|
{
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
}
|
}
|
||||||
*(buffer->data) = '\0';
|
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -88,7 +93,9 @@ int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity)
|
||||||
|
|
||||||
if (buffer->length > 0) {
|
if (buffer->length > 0) {
|
||||||
memcpy(buff, buffer->data, buffer->length);
|
memcpy(buff, buffer->data, buffer->length);
|
||||||
*(buff + buffer->length) = '\0';
|
if (!buffer->binary_mode) {
|
||||||
|
*(buff + buffer->length) = '\0';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(buffer->data);
|
free(buffer->data);
|
||||||
|
|
@ -127,7 +134,7 @@ int fast_buffer_append(FastBuffer *buffer, const char *format, ...)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
*(buffer->data + buffer->length) = '\0'; //restore
|
fast_buffer_set_null_terminator(buffer); //restore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
@ -148,7 +155,7 @@ int fast_buffer_append_buff(FastBuffer *buffer, const char *data, const int len)
|
||||||
|
|
||||||
memcpy(buffer->data + buffer->length, data, len);
|
memcpy(buffer->data + buffer->length, data, len);
|
||||||
buffer->length += len;
|
buffer->length += len;
|
||||||
*(buffer->data + buffer->length) = '\0';
|
fast_buffer_set_null_terminator(buffer);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -171,32 +178,6 @@ int fast_buffer_append_binary(FastBuffer *buffer,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_buffer_append_int(FastBuffer *buffer, const int n)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if ((result=fast_buffer_check(buffer, 16)) != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n)
|
|
||||||
{
|
|
||||||
int result;
|
|
||||||
|
|
||||||
if ((result=fast_buffer_check(buffer, 32)) != 0)
|
|
||||||
{
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
|
int fast_buffer_append_file(FastBuffer *buffer, const char *filename)
|
||||||
{
|
{
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
|
|
||||||
|
|
@ -17,12 +17,14 @@
|
||||||
#define __FAST_BUFFER_H__
|
#define __FAST_BUFFER_H__
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include "common_define.h"
|
#include "shared_func.h"
|
||||||
|
|
||||||
typedef struct fast_buffer {
|
typedef struct fast_buffer {
|
||||||
char *data;
|
char *data;
|
||||||
int alloc_size;
|
int alloc_size;
|
||||||
int length;
|
int length;
|
||||||
|
bool binary_mode;
|
||||||
|
bool check_capacity;
|
||||||
} FastBuffer;
|
} FastBuffer;
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -39,26 +41,39 @@ static inline char *fast_buffer_data(FastBuffer *buffer)
|
||||||
return buffer->data;
|
return buffer->data;
|
||||||
}
|
}
|
||||||
|
|
||||||
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity);
|
int fast_buffer_init_ex(FastBuffer *buffer, const int init_capacity,
|
||||||
|
const bool binary_mode, const bool check_capacity);
|
||||||
|
|
||||||
|
static inline int fast_buffer_init1(FastBuffer *buffer, const int init_capacity)
|
||||||
|
{
|
||||||
|
const bool binary_mode = false;
|
||||||
|
const bool check_capacity = true;
|
||||||
|
return fast_buffer_init_ex(buffer, init_capacity,
|
||||||
|
binary_mode, check_capacity);
|
||||||
|
}
|
||||||
|
|
||||||
static inline int fast_buffer_init(FastBuffer *buffer)
|
static inline int fast_buffer_init(FastBuffer *buffer)
|
||||||
{
|
{
|
||||||
return fast_buffer_init_ex(buffer, 0);
|
const int init_capacity = 0;
|
||||||
|
return fast_buffer_init1(buffer, init_capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define fast_buffer_set_null_terminator(buffer) \
|
||||||
|
if (!buffer->binary_mode) *(buffer->data + buffer->length) = '\0'
|
||||||
|
|
||||||
|
#define fast_buffer_check(buffer, inc_len) \
|
||||||
|
((buffer)->check_capacity ? fast_buffer_check_inc_size(buffer, inc_len) : 0)
|
||||||
|
|
||||||
#define fast_buffer_clear(buffer) fast_buffer_reset(buffer)
|
#define fast_buffer_clear(buffer) fast_buffer_reset(buffer)
|
||||||
|
|
||||||
static inline void fast_buffer_reset(FastBuffer *buffer)
|
static inline void fast_buffer_reset(FastBuffer *buffer)
|
||||||
{
|
{
|
||||||
buffer->length = 0;
|
buffer->length = 0;
|
||||||
*buffer->data = '\0';
|
fast_buffer_set_null_terminator(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void fast_buffer_destroy(FastBuffer *buffer);
|
void fast_buffer_destroy(FastBuffer *buffer);
|
||||||
|
|
||||||
#define fast_buffer_check(buffer, inc_len) \
|
|
||||||
fast_buffer_check_inc_size(buffer, inc_len)
|
|
||||||
|
|
||||||
int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity);
|
int fast_buffer_set_capacity(FastBuffer *buffer, const int capacity);
|
||||||
|
|
||||||
static inline int fast_buffer_check_capacity(FastBuffer *buffer,
|
static inline int fast_buffer_check_capacity(FastBuffer *buffer,
|
||||||
|
|
@ -86,9 +101,47 @@ int fast_buffer_append_buff(FastBuffer *buffer,
|
||||||
int fast_buffer_append_binary(FastBuffer *buffer,
|
int fast_buffer_append_binary(FastBuffer *buffer,
|
||||||
const void *data, const int len);
|
const void *data, const int len);
|
||||||
|
|
||||||
int fast_buffer_append_int(FastBuffer *buffer, const int n);
|
static inline int fast_buffer_append_char(FastBuffer *buffer, const char ch)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n);
|
if ((result=fast_buffer_check(buffer, 1)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
*(buffer->data + buffer->length++) = ch;
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fast_buffer_append_int(FastBuffer *buffer, const int n)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result=fast_buffer_check(buffer, 16)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int fast_buffer_append_int64(FastBuffer *buffer, const int64_t n)
|
||||||
|
{
|
||||||
|
int result;
|
||||||
|
|
||||||
|
if ((result=fast_buffer_check(buffer, 32)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
buffer->length += fc_itoa(n, buffer->data + buffer->length);
|
||||||
|
fast_buffer_set_null_terminator(buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int fast_buffer_append_file(FastBuffer *buffer, const char *filename);
|
int fast_buffer_append_file(FastBuffer *buffer, const char *filename);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -85,7 +85,7 @@ int fast_multi_sock_client_init_ex(FastMultiSockClient *client,
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i=0; i<entry_count; i++) {
|
for (i=0; i<entry_count; i++) {
|
||||||
if ((result=fast_buffer_init_ex(&entries[i].recv_buffer,
|
if ((result=fast_buffer_init1(&entries[i].recv_buffer,
|
||||||
new_init_recv_buffer_size)) != 0)
|
new_init_recv_buffer_size)) != 0)
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,164 @@
|
||||||
|
/*
|
||||||
|
* 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 {
|
||||||
|
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';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
||||||
|
int result;
|
||||||
|
int i;
|
||||||
|
int64_t start_time_us;
|
||||||
|
int append_time_ms;
|
||||||
|
int sprintf_time_ms;
|
||||||
|
double ratio;
|
||||||
|
FastBuffer buffer;
|
||||||
|
DATrunkSpaceLogRecord record;
|
||||||
|
|
||||||
|
log_init();
|
||||||
|
g_current_time = time(NULL);
|
||||||
|
if ((result=fast_buffer_init_ex(&buffer, 256,
|
||||||
|
binary_mode, check_capacity)) != 0)
|
||||||
|
{
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
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++) {
|
||||||
|
fast_buffer_reset(&buffer);
|
||||||
|
log_pack_by_sprintf(&record, &buffer, have_extra_field);
|
||||||
|
}
|
||||||
|
sprintf_time_ms = (get_current_time_us() - start_time_us) / 1000;
|
||||||
|
|
||||||
|
start_time_us = get_current_time_us();
|
||||||
|
for (i=0; i<LOOP; i++) {
|
||||||
|
fast_buffer_reset(&buffer);
|
||||||
|
log_pack_by_append(&record, &buffer, have_extra_field);
|
||||||
|
}
|
||||||
|
append_time_ms = (get_current_time_us() - start_time_us) / 1000;
|
||||||
|
|
||||||
|
if (append_time_ms > 0) {
|
||||||
|
ratio = (double)sprintf_time_ms / (double)append_time_ms;
|
||||||
|
} else {
|
||||||
|
ratio = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("sprintf time: %d ms, append time: %d ms, "
|
||||||
|
"sprintf time / append time: %d%%\n",
|
||||||
|
sprintf_time_ms, append_time_ms,
|
||||||
|
(int)(ratio * 100.00));
|
||||||
|
|
||||||
|
fast_buffer_destroy(&buffer);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue