Skip to content

Commit

Permalink
Faster conversion of integer to string.
Browse files Browse the repository at this point in the history
  • Loading branch information
zxhio committed Dec 30, 2019
1 parent 81d6209 commit 367a14b
Show file tree
Hide file tree
Showing 5 changed files with 154 additions and 7 deletions.
33 changes: 28 additions & 5 deletions Log.cpp
Expand Up @@ -10,6 +10,7 @@

#include "Log.h"
#include "Timestamp.h"
#include "NumToString.h"

#include <chrono>

Expand Down Expand Up @@ -333,23 +334,45 @@ LogLine &LogLine::operator<<(char arg) {
return *this;
}

LogLine &LogLine::operator<<(int16_t arg) {
char tmp[8];
int len = util::i16toa(arg, tmp);
append(tmp, len);
return *this;
}

LogLine &LogLine::operator<<(uint16_t arg) {
char tmp[8];
int len = util::u16toa(arg, tmp);
append(tmp, len);
return *this;
}

LogLine &LogLine::operator<<(int32_t arg) {
append(std::to_string(arg).c_str());
char tmp[12];
int len = util::i32toa(arg, tmp);
append(tmp, len);
return *this;
}

LogLine &LogLine::operator<<(uint32_t arg) {
append(std::to_string(arg).c_str());
char tmp[12];
int len = util::u32toa(arg, tmp);
append(tmp, len);
return *this;
}

LogLine &LogLine::operator<<(int64_t arg) {
append(std::to_string(arg).c_str());
char tmp[24];
int len = util::i64toa(arg, tmp);
append(tmp, len);
return *this;
}

LogLine &LogLine::operator<<(uint64_t arg) {
append(std::to_string(arg).c_str());
char tmp[24];
int len = util::u64toa(arg, tmp);
append(tmp, len);
return *this;
}

Expand All @@ -376,7 +399,7 @@ void setRollSize(uint32_t nMb) { LimLog::singleton()->setRollSize(nMb); }
LogLevel getLogLevel() { return LimLog::singleton()->getLogLevel(); }

// Stringify log level with width of 5.
std::string stringifyLogLevel(LogLevel level) {
const char *stringifyLogLevel(LogLevel level) {
switch (level) {
case LogLevel::FATAL:
return "FATAL";
Expand Down
4 changes: 3 additions & 1 deletion Log.h
Expand Up @@ -162,6 +162,8 @@ class LogLine {
/// Overloaded functions with various types of argument.
LogLine &operator<<(bool arg);
LogLine &operator<<(char arg);
LogLine &operator<<(int16_t arg);
LogLine &operator<<(uint16_t arg);
LogLine &operator<<(int32_t arg);
LogLine &operator<<(uint32_t arg);
LogLine &operator<<(int64_t arg);
Expand All @@ -185,7 +187,7 @@ void setLogLevel(LogLevel level);

/// Get log level.
LogLevel getLogLevel();
std::string stringifyLogLevel(LogLevel level);
const char *stringifyLogLevel(LogLevel level);

/// Set log file (basename and dir, no suffix), defalut `./run`.
/// The Program will automatically add suffix (`.log`).
Expand Down
2 changes: 1 addition & 1 deletion Makefile
Expand Up @@ -3,7 +3,7 @@ CXX = g++
CFLAGS = -std=c++11 -Wall -O3 -g -fno-common
LIBS = -L. -lpthread

LIB_SRCS = Timestamp.cpp Log.cpp
LIB_SRCS = Timestamp.cpp Log.cpp NumToString.cpp
LIB_OBJS = $(LIB_SRCS:.cpp=.o)

TEST_SRCS = LogTest.cpp
Expand Down
96 changes: 96 additions & 0 deletions NumToString.cpp
@@ -0,0 +1,96 @@
//===- NumToString.cpp - Number to string -----------------------*- C++ -*-===//
//
/// \file
/// Faster conversion for number to string with look up digits table.
//
// Author: zxh(definezxh@163.com)
// Date: 2019/12/29 17:48:39
//===----------------------------------------------------------------------===//

#include "NumToString.h"

#include <type_traits>

namespace util {

// The digits table is used to look up for number within 100.
// Each two character corresponds to one digit and ten digits.
static const char DigitsTable[200] = {
'0', '0', '0', '1', '0', '2', '0', '3', '0', '4', '0', '5', '0', '6', '0',
'7', '0', '8', '0', '9', '1', '0', '1', '1', '1', '2', '1', '3', '1', '4',
'1', '5', '1', '6', '1', '7', '1', '8', '1', '9', '2', '0', '2', '1', '2',
'2', '2', '3', '2', '4', '2', '5', '2', '6', '2', '7', '2', '8', '2', '9',
'3', '0', '3', '1', '3', '2', '3', '3', '3', '4', '3', '5', '3', '6', '3',
'7', '3', '8', '3', '9', '4', '0', '4', '1', '4', '2', '4', '3', '4', '4',
'4', '5', '4', '6', '4', '7', '4', '8', '4', '9', '5', '0', '5', '1', '5',
'2', '5', '3', '5', '4', '5', '5', '5', '6', '5', '7', '5', '8', '5', '9',
'6', '0', '6', '1', '6', '2', '6', '3', '6', '4', '6', '5', '6', '6', '6',
'7', '6', '8', '6', '9', '7', '0', '7', '1', '7', '2', '7', '3', '7', '4',
'7', '5', '7', '6', '7', '7', '7', '8', '7', '9', '8', '0', '8', '1', '8',
'2', '8', '3', '8', '4', '8', '5', '8', '6', '8', '7', '8', '8', '8', '9',
'9', '0', '9', '1', '9', '2', '9', '3', '9', '4', '9', '5', '9', '6', '9',
'7', '9', '8', '9', '9'};

static int lut_utoa(uint64_t number, char *to) {
char buf[24];
char *p = buf;
int length = 0;

while (number >= 100) {
const unsigned idx = (number % 100) << 1;
number /= 100;
*p++ = DigitsTable[idx + 1];
*p++ = DigitsTable[idx];
}

if (number < 10) {
*p++ = number + '0';
} else {
const unsigned idx = number << 1;
*p++ = DigitsTable[idx + 1];
*p++ = DigitsTable[idx];
}

length = p - buf;

do {
*to++ = *--p;
} while (p != buf);
*to = '\0';

return length;
}

int lut_itoa(int64_t number, char *to) {
uint64_t n = static_cast<uint64_t>(number);
int sign = 0;
if (number < 0) {
*to++ = '-';
n = ~n + 1;
sign = 1;
}

return lut_utoa(n, to) + sign;
}

int u16toa(uint16_t number, char *to) {
return lut_utoa(static_cast<uint16_t>(number), to);
}
int u32toa(uint32_t number, char *to) {
return lut_utoa(static_cast<uint32_t>(number), to);
}
int u64toa(uint64_t number, char *to) {
return lut_utoa(static_cast<uint64_t>(number), to);
}

int i16toa(int16_t number, char *to) {
return lut_itoa(static_cast<int16_t>(number), to);
}
int i32toa(int32_t number, char *to) {
return lut_itoa(static_cast<int32_t>(number), to);
}
int i64toa(int64_t number, char *to) {
return lut_itoa(static_cast<int64_t>(number), to);
}

} // namespace util
26 changes: 26 additions & 0 deletions NumToString.h
@@ -0,0 +1,26 @@
//===- NumToString.h - Number to string -------------------------*- C++ -*-===//
//
/// \file
/// Faster conversion for number to string.
//
// Author: zxh(definezxh@163.com)
// Date: 2019/12/29 17:45:31
//===----------------------------------------------------------------------===//

#pragma once

#include <stdint.h>

namespace util {

/// Conversion unsigned integer to string \p to , and return string length.
int u16toa(uint16_t number, char *to);
int u32toa(uint32_t number, char *to);
int u64toa(uint64_t number, char *to);

/// Conversion signed integer to string \p to , and return string length.
int i16toa(int16_t number, char *to);
int i32toa(int32_t number, char *to);
int i64toa(int64_t number, char *to);

} // namespace util

0 comments on commit 367a14b

Please sign in to comment.