mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 23:52:03 +00:00
DB/IO: added support for aligned buffer [#CONV-8766].
This commit is contained in:
parent
84d65ee06b
commit
5ca146730b
@ -2,6 +2,9 @@
|
||||
|
||||
#include <boost/noncopyable.hpp>
|
||||
|
||||
#include <DB/Core/Exception.h>
|
||||
#include <DB/Core/ErrorCodes.h>
|
||||
|
||||
#define DBMS_DEFAULT_BUFFER_SIZE 1048576ULL
|
||||
|
||||
|
||||
@ -11,23 +14,26 @@ namespace DB
|
||||
|
||||
/** Замена std::vector<char> для использования в буферах.
|
||||
* Отличается тем, что не делает лишний memset. (И почти ничего не делает.)
|
||||
* Также можно попросить выделять выровненный кусок памяти.
|
||||
*/
|
||||
struct Memory : boost::noncopyable
|
||||
{
|
||||
size_t m_capacity;
|
||||
size_t m_size;
|
||||
char * m_data;
|
||||
size_t alignment;
|
||||
|
||||
Memory() : m_capacity(0), m_size(0), m_data(NULL) {}
|
||||
Memory(size_t size_) : m_capacity(size_), m_size(m_capacity), m_data(size_ ? new char[m_capacity] : NULL) {}
|
||||
Memory() : m_capacity(0), m_size(0), m_data(NULL), alignment(0) {}
|
||||
|
||||
/// Если alignment != 0, то будет выделяться память, выровненная на alignment.
|
||||
Memory(size_t size_, size_t alignment_ = 0) : m_capacity(size_), m_size(m_capacity), alignment(alignment_)
|
||||
{
|
||||
alloc();
|
||||
}
|
||||
|
||||
~Memory()
|
||||
{
|
||||
if (m_data)
|
||||
{
|
||||
delete[] m_data;
|
||||
m_data = NULL;
|
||||
}
|
||||
dealloc();
|
||||
}
|
||||
|
||||
size_t size() const { return m_size; }
|
||||
@ -43,14 +49,45 @@ struct Memory : boost::noncopyable
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_data)
|
||||
delete[] m_data;
|
||||
dealloc();
|
||||
|
||||
m_capacity = new_size;
|
||||
m_size = m_capacity;
|
||||
m_data = new char[m_capacity];
|
||||
|
||||
alloc();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
void alloc()
|
||||
{
|
||||
if (!m_capacity)
|
||||
{
|
||||
m_data = NULL;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!alignment)
|
||||
{
|
||||
m_data = reinterpret_cast<char *>(malloc(m_capacity));
|
||||
|
||||
if (!m_data)
|
||||
throw Exception("Cannot allocate memory (malloc)", ErrorCodes::CANNOT_ALLOCATE_MEMORY);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
int res = posix_memalign(reinterpret_cast<void **>(&m_data), alignment, (m_capacity + alignment - 1) / alignment * alignment);
|
||||
|
||||
if (0 != res)
|
||||
DB::throwFromErrno("Cannot allocate memory (posix_memalign)", ErrorCodes::CANNOT_ALLOCATE_MEMORY, res);
|
||||
}
|
||||
|
||||
void dealloc()
|
||||
{
|
||||
if (m_data)
|
||||
free(reinterpret_cast<void *>(m_data));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@ -64,7 +101,7 @@ protected:
|
||||
Memory memory;
|
||||
public:
|
||||
/// Если передать не-NULL existing_memory, то буфер не будет создавать свой кусок памяти, а будет использовать существующий (и не будет им владеть).
|
||||
BufferWithOwnMemory(size_t size = DBMS_DEFAULT_BUFFER_SIZE, char * existing_memory = NULL) : Base(NULL, 0), memory(existing_memory ? 0 : size)
|
||||
BufferWithOwnMemory(size_t size = DBMS_DEFAULT_BUFFER_SIZE, char * existing_memory = NULL, size_t alignment = 0) : Base(NULL, 0), memory(existing_memory ? 0 : size, alignment)
|
||||
{
|
||||
Base::set(existing_memory ? existing_memory : &memory[0], size);
|
||||
}
|
||||
|
@ -46,8 +46,8 @@ protected:
|
||||
}
|
||||
|
||||
public:
|
||||
WriteBufferFromFileDescriptor(int fd_ = -1, size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE)
|
||||
: BufferWithOwnMemory<WriteBuffer>(buf_size), fd(fd_) {}
|
||||
WriteBufferFromFileDescriptor(int fd_ = -1, size_t buf_size = DBMS_DEFAULT_BUFFER_SIZE, size_t alignment = 0)
|
||||
: BufferWithOwnMemory<WriteBuffer>(buf_size, NULL, alignment), fd(fd_) {}
|
||||
|
||||
/** Можно вызывать для инициализации, если нужный fd не был передан в конструктор.
|
||||
* Менять fd во время работы нельзя.
|
||||
|
Loading…
Reference in New Issue
Block a user