FastFloat library integration

This commit is contained in:
Maksim Kita 2020-11-07 19:48:58 +03:00
parent 459570470e
commit 80d66b8868
8 changed files with 86 additions and 0 deletions

3
.gitmodules vendored
View File

@ -209,3 +209,6 @@
[submodule "contrib/dragonbox"]
path = contrib/dragonbox
url = https://github.com/ClickHouse-Extras/dragonbox.git
[submodule "contrib/fast_float"]
path = contrib/fast_float
url = https://github.com/lemire/fast_float

View File

@ -457,6 +457,7 @@ include (cmake/find/s3.cmake)
include (cmake/find/base64.cmake)
include (cmake/find/parquet.cmake)
include (cmake/find/simdjson.cmake)
include (cmake/find/fast_float.cmake)
include (cmake/find/rapidjson.cmake)
include (cmake/find/fastops.cmake)
include (cmake/find/odbc.cmake)

View File

@ -0,0 +1,15 @@
option (USE_FAST_FLOAT "Use fast_float" ${ENABLE_LIBRARIES})
if (NOT EXISTS "${ClickHouse_SOURCE_DIR}/contrib/fast_float/include/fast_float/fast_float.h")
message (WARNING "submodule contrib/fast_float is missing. to fix try run: \n git submodule update --init --recursive")
if (USE_FAST_FLOAT)
message (${RECONFIGURE_MESSAGE_LEVEL} "Can't find internal fast_float library")
endif()
return()
endif ()
if (USE_FAST_FLOAT)
set(FAST_FLOAT_INCLUDE_DIR "${ClickHouse_SOURCE_DIR}/contrib/fast_float/include/")
endif ()
message(STATUS "Using fast_float=${USE_FAST_FLOAT}")

View File

@ -286,6 +286,10 @@ if (USE_SIMDJSON)
add_subdirectory (simdjson-cmake)
endif()
if (USE_FAST_FLOAT)
add_subdirectory (fast_float)
endif()
if (USE_FASTOPS)
add_subdirectory (fastops-cmake)
endif()

View File

@ -403,6 +403,11 @@ if (USE_MSGPACK)
target_include_directories (clickhouse_common_io SYSTEM BEFORE PUBLIC ${MSGPACK_INCLUDE_DIR})
endif()
if (USE_FAST_FLOAT)
target_link_libraries (clickhouse_common_io PRIVATE fast_float)
target_include_directories (clickhouse_common_io SYSTEM BEFORE PRIVATE ${FAST_FLOAT_INCLUDE_DIR})
endif()
if (USE_ORC)
dbms_target_link_libraries(PUBLIC ${ORC_LIBRARIES})
dbms_target_include_directories(SYSTEM BEFORE PUBLIC ${ORC_INCLUDE_DIR} ${CMAKE_BINARY_DIR}/contrib/orc/c++/include)

View File

@ -14,3 +14,4 @@
#cmakedefine01 USE_GRPC
#cmakedefine01 USE_STATS
#cmakedefine01 CLICKHOUSE_SPLIT_BINARY
#cmakedefine01 USE_FAST_FLOAT

View File

@ -7,6 +7,11 @@ target_link_libraries (read_buffer_perf PRIVATE clickhouse_common_io)
add_executable (read_float_perf read_float_perf.cpp)
target_link_libraries (read_float_perf PRIVATE clickhouse_common_io)
if (USE_FAST_FLOAT)
target_link_libraries (read_float_perf PRIVATE fast_float)
target_include_directories (read_float_perf SYSTEM BEFORE PRIVATE ${FAST_FLOAT_INCLUDE_DIR})
endif()
add_executable (write_buffer write_buffer.cpp)
target_link_libraries (write_buffer PRIVATE clickhouse_common_io)

View File

@ -13,6 +13,9 @@
#include <IO/WriteBufferFromFileDescriptor.h>
#include <Compression/CompressedReadBuffer.h>
#if !defined(ARCADIA_BUILD)
# include <Common/config.h>
#endif
/** How to test:
@ -39,6 +42,52 @@ $ for i in {1..10}; do echo $i; time ./read_float_perf 2 < numbers$i.tsv; done
using namespace DB;
#ifdef USE_FAST_FLOAT
#include <fast_float/fast_float.h>
template <typename T, typename ReturnType>
ReturnType readFloatTextFastFloatImpl(T & x, ReadBuffer & in)
{
static_assert(std::is_same_v<T, double> || std::is_same_v<T, float>, "Argument for readFloatTextImpl must be float or double");
static_assert('a' > '.' && 'A' > '.' && '\n' < '.' && '\t' < '.' && '\'' < '.' && '"' < '.', "Layout of char is not like ASCII"); //-V590
static constexpr bool throw_exception = std::is_same_v<ReturnType, void>;
String buff;
/// TODO: Optimize
/// Currently fast_float interface need begin and end
/// ReadBuffers current begin end can have only part of data
while (!in.eof() && isAlphaNumericASCII(*in.position())) {
buff += *in.position();
++in.position();
}
if (buff.empty())
{
if constexpr (throw_exception)
throw Exception("Cannot read floating point value: no digits read", ErrorCodes::CANNOT_PARSE_NUMBER);
else
return ReturnType(false);
}
auto res = fast_float::from_chars(buff.data(), buff.data() + buff.size(), x);
if (res.ec != std::errc())
{
if constexpr (throw_exception)
throw Exception("Cannot read floating point value", ErrorCodes::CANNOT_PARSE_NUMBER);
else
return ReturnType(false);
}
return ReturnType(true);
}
#endif
template <typename T, void F(T&, ReadBuffer&)>
void NO_INLINE loop(ReadBuffer & in, WriteBuffer & out)
@ -76,6 +125,9 @@ try
if (method == 1) loop<T, readFloatTextPrecise>(in, out);
if (method == 2) loop<T, readFloatTextFast>(in, out);
if (method == 3) loop<T, readFloatTextSimple>(in, out);
#ifdef USE_FAST_FLOAT
if (method == 4) loop<T, readFloatTextFastFloatImpl>(in, out);
#endif
return 0;
}