From e8d5603a49e681188ac72c1540fa59bbf55c80b0 Mon Sep 17 00:00:00 2001 From: Alexey Milovidov Date: Sat, 7 Sep 2013 03:28:20 +0000 Subject: [PATCH] dbms: improved performance: less copying when reading fixed-size columns [#CONV-2944]. --- .../DB/DataTypes/IDataTypeNumberFixed.h | 2 +- dbms/include/DB/IO/ReadBuffer.h | 39 +++++++++++++++++++ dbms/src/DataTypes/DataTypeFixedString.cpp | 2 +- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/dbms/include/DB/DataTypes/IDataTypeNumberFixed.h b/dbms/include/DB/DataTypes/IDataTypeNumberFixed.h index 7d79833adb1..ae9216c61aa 100644 --- a/dbms/include/DB/DataTypes/IDataTypeNumberFixed.h +++ b/dbms/include/DB/DataTypes/IDataTypeNumberFixed.h @@ -55,7 +55,7 @@ public: { typename ColumnType::Container_t & x = dynamic_cast(column).getData(); x.resize(limit); - size_t size = istr.read(reinterpret_cast(&x[0]), sizeof(typename ColumnType::value_type) * limit); + size_t size = istr.readBig(reinterpret_cast(&x[0]), sizeof(typename ColumnType::value_type) * limit); x.resize(size / sizeof(typename ColumnType::value_type)); } diff --git a/dbms/include/DB/IO/ReadBuffer.h b/dbms/include/DB/IO/ReadBuffer.h index 6f62ccb3e55..be0e047c63d 100644 --- a/dbms/include/DB/IO/ReadBuffer.h +++ b/dbms/include/DB/IO/ReadBuffer.h @@ -103,6 +103,45 @@ public: return bytes_copied; } + /** Отличается от предыдущего метода тем, что делает меньше копирований: + * - если в текущем буфере есть данные, то копируем их; + * - если нужны ещё данные, то используем в качестве буфера для чтения to - то есть, читаем сразу куда сказали. + */ + size_t readBig(char * to, size_t n) + { + size_t bytes_copied = 0; + + /// Копируем то, что есть в буфере (уже было считано раньше). + if (pos != working_buffer.end()) + { + size_t bytes_to_copy = std::min(static_cast(working_buffer.end() - pos), n); + std::memcpy(to, pos, bytes_to_copy); + pos += bytes_to_copy; + bytes_copied += bytes_to_copy; + } + + /// Запоминаем старый буфер для чтения. + Buffer old_buffer = internal_buffer; + + /// Если не хватило. + while (bytes_copied < n) + { + /// Выставляем в качестве буфера для чтения кусок памяти, куда нужно положить результат. + set(to + bytes_copied, n - bytes_copied); + + /// Эта штука читает данные + if (!next()) + break; + + bytes_copied += working_buffer.size(); + } + + /// Выставляем обратно старый буфер. + set(old_buffer.begin(), old_buffer.size()); + + return bytes_copied; + } + /** Читает n байт, если есть меньше - кидает исключение. */ void readStrict(char * to, size_t n) { diff --git a/dbms/src/DataTypes/DataTypeFixedString.cpp b/dbms/src/DataTypes/DataTypeFixedString.cpp index cac908d515f..cac2c57a47a 100644 --- a/dbms/src/DataTypes/DataTypeFixedString.cpp +++ b/dbms/src/DataTypes/DataTypeFixedString.cpp @@ -55,7 +55,7 @@ void DataTypeFixedString::deserializeBinary(IColumn & column, ReadBuffer & istr, size_t max_bytes = limit * n; data.resize(max_bytes); - size_t read_bytes = istr.read(reinterpret_cast(&data[0]), max_bytes); + size_t read_bytes = istr.readBig(reinterpret_cast(&data[0]), max_bytes); if (read_bytes % n != 0) throw Exception("Cannot read all data of type FixedString",