Removed all trailing whitespaces [#CLICKHOUSE-2]. find . -name '*.h' -or -name '*.cpp' -or -name '*.cmake' -or -name 'CMakeLists.txt' -or -name '*.html' -or -name '*.xml' | grep -v contrib | xargs sed -i -r -e 's/\s+$//'

This commit is contained in:
Alexey Milovidov 2017-03-31 19:00:30 +03:00
parent f5a7498559
commit 4f44445ff0
42 changed files with 211 additions and 211 deletions

View File

@ -16,33 +16,33 @@
#
# Usage:
# set(ENV{Poco_DIR} path/to/poco/sdk)
# find_package(Poco REQUIRED OSP Data Crypto)
# find_package(Poco REQUIRED OSP Data Crypto)
#
# On completion, the script defines the following variables:
#
#
# - Compound variables:
# Poco_FOUND
# Poco_FOUND
# - true if all requested components were found.
# Poco_LIBRARIES
# Poco_LIBRARIES
# - contains release (and debug if available) libraries for all requested components.
# It has the form "optimized LIB1 debug LIBd1 optimized LIB2 ...", ready for use with the target_link_libraries command.
# Poco_INCLUDE_DIRS
# - Contains include directories for all requested components.
#
# - Component variables:
# Poco_Xxx_FOUND
# - Where Xxx is the properly cased component name (eg. 'Util', 'OSP').
# Poco_Xxx_FOUND
# - Where Xxx is the properly cased component name (eg. 'Util', 'OSP').
# True if a component's library or debug library was found successfully.
# Poco_Xxx_LIBRARY
# Poco_Xxx_LIBRARY
# - Library for component Xxx.
# Poco_Xxx_LIBRARY_DEBUG
# Poco_Xxx_LIBRARY_DEBUG
# - debug library for component Xxx
# Poco_Xxx_INCLUDE_DIR
# - include directory for component Xxx
#
# - OSP BundleCreator variables: (i.e. bundle.exe on windows, bundle on unix-likes)
# (is only discovered if OSP is a requested component)
# Poco_OSP_Bundle_EXECUTABLE_FOUND
# Poco_OSP_Bundle_EXECUTABLE_FOUND
# - true if the bundle-creator executable was found.
# Poco_OSP_Bundle_EXECUTABLE
# - the path to the bundle-creator executable.
@ -52,24 +52,24 @@
set(Poco_HINTS
/usr/local
C:/AppliedInformatics
${Poco_DIR}
${Poco_DIR}
$ENV{Poco_DIR}
)
if(NOT Poco_ROOT_DIR)
# look for the root directory, first for the source-tree variant
find_path(Poco_ROOT_DIR
find_path(Poco_ROOT_DIR
NAMES Foundation/include/Poco/Poco.h
HINTS ${Poco_HINTS}
)
if(NOT Poco_ROOT_DIR)
# this means poco may have a different directory structure, maybe it was installed, let's check for that
message(STATUS "Looking for Poco install directory structure.")
find_path(Poco_ROOT_DIR
find_path(Poco_ROOT_DIR
NAMES include/Poco/Poco.h
HINTS ${Poco_HINTS}
)
if(NOT Poco_ROOT_DIR)
if(NOT Poco_ROOT_DIR)
# poco was still not found -> Fail
if(Poco_FIND_REQUIRED)
message(FATAL_ERROR "Poco: Could not find Poco install directory")
@ -91,7 +91,7 @@ if(WIN32)
find_path(Poco_RUNTIME_LIBRARY_DIRS
NAMES PocoFoundation.dll
HINTS ${Poco_ROOT_DIR}
PATH_SUFFIXES
PATH_SUFFIXES
bin
lib
)
@ -103,17 +103,17 @@ if(Poco_INSTALLED)
endif()
# append the default minimum components to the list to find
list(APPEND components
${Poco_FIND_COMPONENTS}
list(APPEND components
${Poco_FIND_COMPONENTS}
# default components:
"Util"
"Util"
"Foundation"
)
list(REMOVE_DUPLICATES components) # remove duplicate defaults
foreach( component ${components} )
#if(NOT Poco_${component}_FOUND)
# include directory for the component
if(NOT Poco_${component}_INCLUDE_DIR)
if (${component} STREQUAL "DataODBC")
@ -127,7 +127,7 @@ foreach( component ${components} )
set (component_alt ${component})
endif ()
find_path(Poco_${component}_INCLUDE_DIR
NAMES
NAMES
Poco/${component}.h # e.g. Foundation.h
Poco/${component}/${component}.h # e.g. OSP/OSP.h Util/Util.h
Poco/${component_alt}/${component}.h # e.g. Net/NetSSL.h
@ -148,8 +148,8 @@ foreach( component ${components} )
# release library
if(NOT Poco_${component}_LIBRARY)
find_library(
Poco_${component}_LIBRARY
NAMES Poco${component}
Poco_${component}_LIBRARY
NAMES Poco${component}
HINTS ${Poco_ROOT_DIR}
PATH_SUFFIXES
lib
@ -198,9 +198,9 @@ endif()
if(${Poco_OSP_FOUND})
# find the osp bundle program
find_program(
Poco_OSP_Bundle_EXECUTABLE
Poco_OSP_Bundle_EXECUTABLE
NAMES bundle
HINTS
HINTS
${Poco_RUNTIME_LIBRARY_DIRS}
${Poco_ROOT_DIR}
PATH_SUFFIXES

View File

@ -47,12 +47,12 @@ public:
{
setEmpty();
}
AutoArray(size_t size_)
{
init(size_, false);
}
/** Не будут вызваны конструкторы по-умолчанию для элементов.
* В этом случае, вы должны вставить все элементы с помощью функции place и placement new,
* так как для них потом будут вызваны деструкторы.
@ -61,13 +61,13 @@ public:
{
init(size_, true);
}
/** Инициализирует все элементы копирующим конструктором с параметром value.
*/
AutoArray(size_t size_, const T & value)
{
init(size_, true);
for (size_t i = 0; i < size_; ++i)
{
new (place(i)) T(value);
@ -134,7 +134,7 @@ public:
{
return elem(i);
}
const T & operator[](size_t i) const
{
return elem(i);
@ -234,7 +234,7 @@ private:
setEmpty();
return;
}
data = new char[size_ * sizeof(T) + sizeof(size_t)];
data += sizeof(size_t);
m_size() = size_;

View File

@ -28,7 +28,7 @@ namespace DB
* - один или несколько пакетов Data.
* Конец данных определается по отправленному пустому блоку.
* Затем сервер отправляет клиенту пакет EndOfStream.
*
*
* Если запрос типа SELECT или другой, то сервер передаёт набор пакетов одного из следующих видов:
* - Data - данные результата выполнения запроса (один блок);
* - Progress - прогресс выполнения запроса;
@ -39,12 +39,12 @@ namespace DB
* Также, клиент может передать на сервер пакет Cancel - отмена выполнения запроса.
* В этом случае, сервер может прервать выполнение запроса и вернуть неполные данные;
* но клиент всё равно должен читать все пакеты до EndOfStream.
*
*
* Перед пакетом EndOfStream, если есть профайлинговая информация и ревизия клиента достаточно новая,
* может быть отправлен пакет Totals и/или ProfileInfo.
* Totals - блок с тотальными значениями.
* ProfileInfo - данные профайлинга - сериализованная структура BlockStreamProfileInfo.
*
*
* При запросах, которые возвращают данные, сервер, перед обработкой запроса,
* отправляет заголовочный блок, содержащий описание столбцов из запроса, но с нулем строк.
* Используя этот заголовочный блок, клиент может заранее проинициализировать формат вывода

View File

@ -19,7 +19,7 @@ public:
ASTDropQuery() = default;
ASTDropQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return (detach ? "DetachQuery_" : "DropQuery_") + database + "_" + table; };

View File

@ -29,7 +29,7 @@ public:
ASTRenameQuery() = default;
ASTRenameQuery(const StringRange range_) : IAST(range_) {}
/** Получить текст, который идентифицирует этот элемент. */
String getID() const override { return "Rename"; };

View File

@ -56,7 +56,7 @@ public:
if (sigemptyset(&sig_set)
|| sigaddset(&sig_set, SIGINT))
throwFromErrno("Cannot manipulate with signal set.", ErrorCodes::CANNOT_MANIPULATE_SIGSET);
block();
}
@ -69,9 +69,9 @@ public:
{
if (!active)
return false;
timespec timeout = { 0, 0 };
if (-1 == sigtimedwait(&sig_set, nullptr, &timeout))
{
if (errno == EAGAIN)

View File

@ -107,7 +107,7 @@ template < typename keytype, typename hashtype >
bool AvalancheTest ( pfHash hash, const int reps )
{
Rand r(48273);
const int keybytes = sizeof(keytype);
const int hashbytes = sizeof(hashtype);
@ -121,7 +121,7 @@ bool AvalancheTest ( pfHash hash, const int reps )
std::vector<int> bins(keybits*hashbits,0);
calcBias<keytype,hashtype>(hash,bins,reps,r);
//----------
bool result = true;

View File

@ -51,7 +51,7 @@ struct Rand
{
uint32_t t = x ^ (x << 11);
x = y; y = z; z = w;
w = w ^ (w >> 19) ^ t ^ (t >> 8);
w = w ^ (w >> 19) ^ t ^ (t >> 8);
}
uint32_t rand_u32 ( void )
@ -61,7 +61,7 @@ struct Rand
return x;
}
uint64_t rand_u64 ( void )
uint64_t rand_u64 ( void )
{
mix();

View File

@ -39,7 +39,7 @@ int main(int argc, char ** argv)
}
std::cerr << std::endl;
{
size_t n = 10;
using T = std::string;
@ -58,7 +58,7 @@ int main(int argc, char ** argv)
Arr arr2 = std::move(arr);
std::cerr << arr.size() << ", " << arr2.size() << std::endl;
for (size_t i = 0; i < arr2.size(); ++i)
std::cerr << arr2[i] << std::endl;
}
@ -78,7 +78,7 @@ int main(int argc, char ** argv)
Arr key(n);
for (size_t j = 0; j < n; ++j)
key[j] = DB::toString(rand());
map[std::move(key)] = "Hello, world! " + DB::toString(i);
}
@ -88,7 +88,7 @@ int main(int argc, char ** argv)
for (size_t j = 0; j < n; ++j)
std::cerr << (j == 0 ? "" : ", ") << it->first[j];
std::cerr << "]";
std::cerr << ":\t" << it->second << std::endl;
}

View File

@ -61,7 +61,7 @@ int main(int argc, char ** argv)
<< " (" << rows / watch.elapsedSeconds() << " rows/sec., " << bytes / 1000000.0 / watch.elapsedSeconds() << " MB/sec.)"
<< std::endl;
}
/* {
Stopwatch watch;

View File

@ -120,7 +120,7 @@ int test_vectors()
hash.update(in, part);
hash.update(in + part, i - part);
hash.get128(out);
uint64_t test_vector;

View File

@ -19,7 +19,7 @@ int main(int argc, char ** argv)
{
std::cerr << std::fixed << std::setprecision(3);
std::ofstream devnull("/dev/null");
DB::ReadBufferFromFileDescriptor in(STDIN_FILENO);
size_t n = atoi(argv[1]);
size_t elems_show = 1;
@ -116,7 +116,7 @@ int main(int argc, char ** argv)
DB::Arena pool;
RefsSet set;
Stopwatch watch;
for (Vec::iterator it = vec.begin(); it != vec.end(); ++it)
set[StringRef(pool.insert(it->data(), it->size()), it->size())] = 0;

View File

@ -53,7 +53,7 @@ int main(int argc, char ** argv)
printType(DB::NumberTraits::ResultOfFloatingPointDivision<DB::UInt32, DB::Int16>::Type()); std::cout << std::endl;
printType(DB::NumberTraits::ResultOfIntegerDivision<DB::UInt8, DB::Int16>::Type()); std::cout << std::endl;
printType(DB::NumberTraits::ResultOfModulo<DB::UInt32, DB::Int8>::Type()); std::cout << std::endl;
ifLeftType<DB::UInt8>();
ifLeftType<DB::UInt16>();
ifLeftType<DB::UInt32>();
@ -64,6 +64,6 @@ int main(int argc, char ** argv)
ifLeftType<DB::Int64>();
ifLeftType<DB::Float32>();
ifLeftType<DB::Float64>();
return 0;
}

View File

@ -12,7 +12,7 @@
int main(int argc, char ** argv)
{
using namespace DB;
try
{
UncompressedCache cache(1024);

View File

@ -23,7 +23,7 @@ namespace test
++buf.position();
negative = true;
}
if (*buf.position() == '0')
{
++buf.position();

View File

@ -22,13 +22,13 @@ int main(int argc, char ** argv)
DB::readIntText(a, in);
in.ignore();
DB::readFloatText(b, in);
in.ignore();
DB::readEscapedString(c, in);
in.ignore();
DB::readQuotedString(d, in);
std::cout << a << ' ' << b << ' ' << c << '\t' << '\'' << d << '\'' << std::endl;

View File

@ -24,13 +24,13 @@ int main(int argc, char ** argv)
{
DB::readIntText(a, in);
in.ignore();
DB::readFloatText(b, in);
in.ignore();
DB::readEscapedString(c, in);
in.ignore();
DB::readQuotedString(d, in);
in.ignore();

View File

@ -19,7 +19,7 @@ int main(int argc, char ** argv)
std::string s;
std::cerr << static_cast<Int64>(x1) << std::endl;
{
DB::WriteBufferFromString wb(s);
DB::writeIntText(x1, wb);

View File

@ -13,12 +13,12 @@ int main(int argc, char ** argv)
int repeats = 1;
if (argc >= 2)
repeats = atoi(argv[1]);
std::string text((std::istreambuf_iterator<char>(std::cin)),
std::istreambuf_iterator<char>());
std::cout << "Text length: " << text.size() << std::endl;
Stopwatch timer;
std::string str1;
{
@ -31,9 +31,9 @@ int main(int argc, char ** argv)
double t = timer.elapsedSeconds();
std::cout << "Wrote to string in " << t << "s at " << text.size() / 1e6 * repeats / t << "MB/s." << std::endl;
std::cout << "String length: " << str1.size() << "(" << (str1.size() == text.size() * repeats ? "as " : "un") << "expected)" << std::endl;
timer.restart();
std::string str2;
{
DB::WriteBufferFromString simple_buf(str2);

View File

@ -24,10 +24,10 @@ int main(int argc, char ** argv)
DB::writeIntText(a, out);
DB::writeChar(' ', out);
DB::writeFloatText(b, out);
DB::writeChar(' ', out);
DB::writeEscapedString(c, out);
DB::writeChar('\t', out);

View File

@ -24,10 +24,10 @@ int main(int argc, char ** argv)
{
DB::writeIntText(a, out);
DB::writeChar(' ', out);
DB::writeFloatText(b, out);
DB::writeChar(' ', out);
DB::writeEscapedString(c, out);
DB::writeChar('\t', out);

View File

@ -143,7 +143,7 @@ int main(int argc, char ** argv)
std::unordered_map<Key, Value, DefaultHash<Key> > map;
for (size_t i = 0; i < n; ++i)
++map[data[i]];
watch.stop();
std::cerr << std::fixed << std::setprecision(2)
<< "std::unordered_map. Size: " << map.size()
@ -160,7 +160,7 @@ int main(int argc, char ** argv)
map.set_empty_key(-1ULL);
for (size_t i = 0; i < n; ++i)
++map[data[i]];
watch.stop();
std::cerr << std::fixed << std::setprecision(2)
<< "google::dense_hash_map. Size: " << map.size()

View File

@ -437,7 +437,7 @@ int main(int argc, char ** argv)
std::unordered_map<Key, Value, DefaultHash<Key> > map;
for (size_t i = 0; i < n; ++i)
++map[data[i]];
watch.stop();
std::cerr << std::fixed << std::setprecision(2)
<< "std::unordered_map. Size: " << map.size()
@ -454,7 +454,7 @@ int main(int argc, char ** argv)
map.set_empty_key(Key("\0", 1));
for (size_t i = 0; i < n; ++i)
++map[data[i]];
watch.stop();
std::cerr << std::fixed << std::setprecision(2)
<< "google::dense_hash_map. Size: " << map.size()

View File

@ -595,7 +595,7 @@ int Server::main(const std::vector<std::string> & args)
}
LOG_DEBUG(
log, "Closed connections." << (current_connections ? " But " + std::to_string(current_connections) + " remains."
log, "Closed connections." << (current_connections ? " But " + std::to_string(current_connections) + " remains."
+ " Tip: To increase wait time add to config: <shutdown_wait_unfinished>60</shutdown_wait_unfinished> ." : ""));
main_config_reloader.reset();

View File

@ -105,7 +105,7 @@ MergeTreeData::MutableDataPartPtr MergeTreeDataWriter::writeTempPart(BlockWithDa
size_t part_size = (block.rows() + data.index_granularity - 1) / data.index_granularity;
String part_name = ActiveDataPartSet::getPartName(
DayNum_t(min_date), DayNum_t(max_date),
temp_index, temp_index, 0);

View File

@ -339,7 +339,7 @@ bool StorageMergeTree::merge(
/// Logging
Stopwatch stopwatch;
auto new_part = merger.mergePartsToTemporaryPart(
merging_tagger->parts, merged_name, *merge_entry_ptr, aio_threshold, time(0), merging_tagger->reserved_space.get());

View File

@ -1157,7 +1157,7 @@ bool StorageReplicatedMergeTree::executeLogEntry(const LogEntry & entry)
/// Logging
Stopwatch stopwatch;
auto part = merger.mergePartsToTemporaryPart(
parts, entry.new_part_name, *merge_entry, aio_threshold, entry.create_time, reserved_space.get());
@ -2077,11 +2077,11 @@ bool StorageReplicatedMergeTree::fetchPart(const String & part_name, const Strin
ReplicatedMergeTreeAddress address(getZooKeeper()->get(replica_path + "/host"));
Stopwatch stopwatch;
MergeTreeData::MutableDataPartPtr part = fetcher.fetchPart(
part_name, replica_path, address.host, address.replication_port, to_detached);
if (!to_detached)
{
zkutil::Ops ops;
@ -2386,7 +2386,7 @@ bool StorageReplicatedMergeTree::optimize(const String & partition, bool final,
/// Logging
Stopwatch stopwatch;
auto new_part = unreplicated_merger->mergePartsToTemporaryPart(
parts, merged_name, *merge_entry, settings.min_bytes_to_use_direct_io, time(0));

View File

@ -11,11 +11,11 @@
<header class="caption">
<h1>Параллельный и распределённый GROUP BY</h1>
</header>
<section class="slide" id="cover">
<h1 style="margin-top: 200px">Параллельный и распределённый GROUP BY</h1>
</section>
<section class="slide">
<h2>Обо мне</h2>
<p>Алексей, разработчик ClickHouse.</p>
@ -28,12 +28,12 @@
<p>Один запрос &mdash; много данных на входе, мало на выходе.</p>
<p>Данные нужно агрегировать налету.</p>
</section>
<section class="slide">
<h2>Метрика 2.0</h2>
<img src="pictures/metrika2.png" style="height:70%"/>
</section>
<section class="slide">
<h2>Пример запроса</h2>
<p style="font-family: Monospace">SELECT MobilePhoneModel, COUNT(DISTINCT UserID) AS u<br />
@ -42,7 +42,7 @@
<b>GROUP BY</b> MobilePhoneModel<br />
ORDER BY u DESC</p>
</section>
<section class="slide">
<h2>&nbsp;</h2>
<p>Чтобы быстро обрабатывать запросы, данные необходимо:</p>
@ -54,7 +54,7 @@
<p>Конвейер выполнения запроса:</p>
<p>&mdash; фильтрация, JOIN, <b>агрегация</b>, сортировка...</p>
</section>
<section class="slide">
<h2 style="font-size: 45px;">Как тестировать производительность?</h2>
<p>Бенчмарки должны быть:</p>
@ -65,7 +65,7 @@
<li>автоматизированные.</li>
</ul>
</section>
<section class="slide">
<h2>Пример бенчмарка (не лучшего)</h2>
<pre style="white-space: pre; font-family: Monospace; font-size: 14px; line-height: 1.25em;">/** Выполнять так:
@ -82,7 +82,7 @@ for file in <b>MobilePhoneModel PageCharset Params URLDomain UTMSource Referer U
if [[ $TOTAL_ELEMS -gt 25000000 ]]; then break; fi
./hash_map_string_3 $size $method < ${file}.bin 2>&1 |
grep HashMap | grep -oE '[0-9\.]+ elem';
done | awk -W interactive '{ if ($1 > x) { x = $1 }; printf(".") } END { print x }' |
done | awk -W interactive '{ if ($1 > x) { x = $1 }; printf(".") } END { print x }' |
tee /tmp/hash_map_string_3_res;
CUR_RESULT=$(cat /tmp/hash_map_string_3_res | tr -d '.')
if [[ $CUR_RESULT -gt $BEST_RESULT ]]; then
@ -95,15 +95,15 @@ for file in <b>MobilePhoneModel PageCharset Params URLDomain UTMSource Referer U
done
*/</pre>
</section>
<section class="slide">
<h2>Агрегация</h2>
</section>
<section class="slide">
<h2>Одна машина, одно ядро</h2>
</section>
<section class="slide">
<h2>Плохой способ</h2>
<p>Читаем данные в массив; сортируем по ключу;
@ -117,7 +117,7 @@ done
Отвратительно работает при N > M &mdash; в типичном случае.
Тратится O(N) оперативки на промежуточные данные вместо O(M).</p>
</section>
<section class="slide">
<h2>Хороший способ</h2>
<p>Читаем данные, кладём в ассоциативный массив</p>
@ -131,19 +131,19 @@ done
<p>Бинарное дерево. Skip-лист. B-дерево. </p>
<p>Трай. Трай+хэш-таблица...</p>
</section>
<section class="slide">
<h2>Бинарное дерево</h2>
<p>&minus; слишком большой оверхед на элемент;</p>
<p>&minus; отвратительная кэш-локальность;</p>
<p>&minus; вообще тормозит.</p>
</section>
<section class="slide">
<h2>Skip-лист. Трай. B-дерево...</h2>
<p>&minus; вообще для другой задачи;</p>
</section>
<section class="slide">
<h2>Lookup-таблица</h2>
<p>+ прекрасно для агрегации по числовым ключам не более ~16 бит;</p>
@ -155,12 +155,12 @@ done
<p>+ моя любимая структура данных;</p>
<p>&minus; много деталей.</p>
</section>
<section class="slide">
<h2>Трай+хэш-таблица</h2>
<p>+ иногда кое что в этом есть, см. далее;</p>
</section>
<section class="slide">
<h2>Одна машина, много ядер</h2>
</section>
@ -168,18 +168,18 @@ done
<section class="slide">
<h2>1. Тривиальный способ</h2>
<p>Разные потоки читают разные данные по мере возможности.
<p>Разные потоки читают разные данные по мере возможности.
Агрегируют независимо в свои локальные хэш-таблицы.
Когда все данные прочитаны, мержим все хэш-таблицы в одну.
Например, идём по всем локальным хэш-таблицам кроме первой
Когда все данные прочитаны, мержим все хэш-таблицы в одну.
Например, идём по всем локальным хэш-таблицам кроме первой
и перекладываем всё в первую.
Фаза чтения данных и предварительной агрегации распараллеливается.
Фаза мержа выполняется последовательно.
Пусть N &mdash; общее число данных, а M &mdash; количество ключей.
O(M) работы выполняется последовательно
и при большом M (кардинальность GROUP BY)
O(M) работы выполняется последовательно
и при большом M (кардинальность GROUP BY)
работа плохо распараллеливается.
Достоинства: тривиально.
@ -193,42 +193,42 @@ O(M) работы выполняется последовательно
<p>Для каждого блока данных, выполняем агрегацию в две стадии:
Стадия 1.
Разные потоки будут обрабатывать разные куски блока, какие успеют.
В каждом потоке, с помощью отдельной хэш-функции,
хэшируем ключ в номер потока и запоминаем его.
Стадия 1.
Разные потоки будут обрабатывать разные куски блока, какие успеют.
В каждом потоке, с помощью отдельной хэш-функции,
хэшируем ключ в номер потока и запоминаем его.
hash: key -> bucket_num
Стадия 2.
Каждый поток идёт по всему блоку данных
Стадия 2.
Каждый поток идёт по всему блоку данных
и берёт для агрегации только строки с нуждым номером корзины.
Модификация: можно всё в одну стадию &mdash; тогда каждый поток
будет вычислять хэш-функцию от всех строк заново:
Модификация: можно всё в одну стадию &mdash; тогда каждый поток
будет вычислять хэш-функцию от всех строк заново:
подходит, если это дёшево.
</section>
<section class="slide">
<p>
Достоинства:
+ хорошо масштабируется при большой кардинальности
+ хорошо масштабируется при большой кардинальности
и равномерном распределении ключей;
+ идейная простота.
Недостатки:
&minus; если объём данных распределён неравномерно по ключам,
&minus; если объём данных распределён неравномерно по ключам,
то стадия 2 плохо масштабируется.
Это типичный случай.
Это типичный случай.
Почти всегда объём данных по ключам распределён по power law.
Ещё недостатки:
&minus; если размер блока маленький, то получается слишком
мелко-гранулированная многопоточность:
&minus; если размер блока маленький, то получается слишком
мелко-гранулированная многопоточность:
большой оверхед на синхронизацию;
&minus; если размер блока большой, то плохая кэш-локальность;
&minus; на второй стадии, часть memory bandwidth умножается на число потоков;
&minus; нужно вычислять ещё одну хэш-функцию,
&minus; нужно вычислять ещё одну хэш-функцию,
она должна быть независима от той, что в хэш-таблице;</p>
</section>
@ -238,7 +238,7 @@ O(M) работы выполняется последовательно
<p>Отресайзим полученные в разных потоках хэш-таблицы к одному размеру.
Разобъём их неявно на разные подмножества ключей.
В разных потоках будем мержить соответствующие
В разных потоках будем мержить соответствующие
подмножества ключей хэш-таблиц.
Рисунок на доске.
@ -252,18 +252,18 @@ O(M) работы выполняется последовательно
<h2>4. Ordered мерж хэш-таблиц</h2>
<p>Для open addressing linear probing хэш-таблиц, или для chaining хэш-таблиц,
данные в хэш-таблице расположены почти упорядоченно
данные в хэш-таблице расположены почти упорядоченно
по остатку от деления хэш-функции на размер хэш-таблицы
&mdash; с точностью до цепочек разрешения коллизий.
Отресайзим полученные в разных потоках хэш-таблицы к одному размеру.
Сделаем ordered iterator, который будет
Сделаем ordered iterator, который будет
перебирать данные в хэш-таблице в фиксированном порядке.
Объём работы на итерирование:
Объём работы на итерирование:
количество цепочек разрешения коллизий * средний квадрат длин цепочек.
Сделаем merging iterator, который с помощью heap (priority queue)
Сделаем merging iterator, который с помощью heap (priority queue)
будет перебирать все хэш-таблицы разом.
</section>
@ -279,9 +279,9 @@ O(M) работы выполняется последовательно
&minus; отвратительно сложный код;
&minus; для open addressing linear probing хэш-таблиц,
&minus; для open addressing linear probing хэш-таблиц,
средний квадрат длин цепочек разрешения коллизий слишком большой;
&minus; priority queue тормозит;
&minus; стадия мержа не распараллеливается*
@ -294,9 +294,9 @@ O(M) работы выполняется последовательно
<section class="slide">
<h2 style="font-size: 40px;">5. Robin Hood ordered мерж хэш-таблиц</h2>
<p>Если использовать Robin Hood хэш-таблицу, то данные
(за исключением O(1) граничных цепочек разрешения коллизий)
будут полностью упорядочены
<p>Если использовать Robin Hood хэш-таблицу, то данные
(за исключением O(1) граничных цепочек разрешения коллизий)
будут полностью упорядочены
по остатку от деления хэш-функции на размер хэш-таблицы.
Достоинства:
@ -326,12 +326,12 @@ O(M) работы выполняется последовательно
Недостатки:
&minus; в типичном случае данные распределены сильно неравномерно,
&minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей корзине.
&minus; в случае маленькой хэш-таблицы, слишком тормозит.
Достоинства: если данные почему-то распределены равномерно,
Достоинства: если данные почему-то распределены равномерно,
то кое-как масштабируется.</p>
</section>
@ -341,11 +341,11 @@ O(M) работы выполняется последовательно
<p>Недостатки:
&minus; spin-lock &mdash; это очень опасно;
очень сложно тестировать производительность;
&minus; spin-lock &mdash; это очень опасно;
очень сложно тестировать производительность;
вы обязательно сделаете отстой.
&minus; в типичном случае данные распределены сильно неравномерно,
&minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей ячейке.</p>
</section>
@ -357,7 +357,7 @@ O(M) работы выполняется последовательно
&minus; lock free хэш-таблицы либо нельзя ресайзить, либо они очень сложные;
&minus; в типичном случае данные распределены сильно неравномерно,
&minus; в типичном случае данные распределены сильно неравномерно,
и потоки будут конкурировать на одной горячей ячейке:
false sharing, тормоза.
@ -370,14 +370,14 @@ O(M) работы выполняется последовательно
<section class="slide">
<h2 style="font-size: 35px;">10. Shared хэш-таблица + thread local хэш-таблицы</h2>
<p>Пытаемся положить в shared хэш-таблицу путём блокирования ячейки;
если ячейка уже заблокирована &mdash; кладём к локальную хэш-таблицу.
<p>Пытаемся положить в shared хэш-таблицу путём блокирования ячейки;
если ячейка уже заблокирована &mdash; кладём к локальную хэш-таблицу.
Тогда горячие ключи попадут в локальные хэш-таблицы.
Локальные хэш-таблицы будут маленькими.
Тогда горячие ключи попадут в локальные хэш-таблицы.
Локальные хэш-таблицы будут маленькими.
В конце мержим все локальные хэш-таблицы в глобальную.
Дополнения: можно сначала смотреть
Дополнения: можно сначала смотреть
на наличие ключа в локальной хэш-таблице.
Достоинства:
@ -387,7 +387,7 @@ O(M) работы выполняется последовательно
Недостатки:
&minus; много лукапов, много инструкций &mdash; в целом довольно медленно.
Даже не смотря на то, что thread local хэш-таблица
Даже не смотря на то, что thread local хэш-таблица
зачастую ещё и cache local.</p>
</section>
@ -395,18 +395,18 @@ O(M) работы выполняется последовательно
<section class="slide">
<h2>11. Two-level хэш-таблица</h2>
<p>На первой стадии, в каждом потоке независимо
кладём данные в свои num_buckets = 256 хэш-таблиц,
<p>На первой стадии, в каждом потоке независимо
кладём данные в свои num_buckets = 256 хэш-таблиц,
хранящих разные ключи.
В какую из них класть (номер корзины)
определяется другой хэш-функцией,
В какую из них класть (номер корзины)
определяется другой хэш-функцией,
либо отдельным байтом хэш-функции.
Имеем num_threads * num_buckets хэш-таблиц.
На второй стадии мержим состояния
num_threads * num_buckets хэш-таблиц
На второй стадии мержим состояния
num_threads * num_buckets хэш-таблиц
в одни num_buckets хэш-таблиц,
распараллеливая мерж по bucket-ам.
</section>
@ -427,13 +427,13 @@ num_threads * num_buckets хэш-таблиц
Недостатки:
&minus; при большой кардинальности, во время мержа
&minus; при большой кардинальности, во время мержа
делается до такого же объёма работ как на первой стадии;
&minus; при маленькой кардинальности,
&minus; при маленькой кардинальности,
слишком много отдельных хэш-таблиц;
&minus; при маленькой кардинальности,
&minus; при маленькой кардинальности,
работает несколько медленнее тривиального способа;</p>
</section>
@ -453,7 +453,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide">
<h2>Много машин, много ядер</h2>
<p>На разных машинах расположены части данных,
<p>На разных машинах расположены части данных,
которые надо обработать.
Отличия от shared memory:
@ -466,7 +466,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide">
<h2>1. Тривиальный способ</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса.
<p>Передаём промежуточные результаты на сервер-инициатор запроса.
Последовательно кладём всё в одну хэш-таблицу.
Достоинства:
@ -484,7 +484,7 @@ num_threads * num_buckets хэш-таблиц
<section class="slide">
<h2>2. Ordered merge</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса
<p>Передаём промежуточные результаты на сервер-инициатор запроса
в заданном порядке. Мержим.
Достоинства:
@ -501,15 +501,15 @@ num_threads * num_buckets хэш-таблиц
<section class="slide">
<h2>3. Partitioned merge</h2>
<p>Передаём промежуточные результаты на сервер-инициатор запроса,
разбитыми на отдельные согласованные корзины-партиции,
в заданном порядке корзин.
<p>Передаём промежуточные результаты на сервер-инициатор запроса,
разбитыми на отдельные согласованные корзины-партиции,
в заданном порядке корзин.
Мержим по одной или по несколько корзин одновременно.
Достоинства:
+ тратится до в num_buckets раз меньше оперативки, чем размер результата;
+ можно легко распараллелить, мержа сразу несколько корзин
+ можно легко распараллелить, мержа сразу несколько корзин
&mdash; отлично масштабируется по ядрам.
Недостатки:
@ -528,8 +528,8 @@ num_threads * num_buckets хэш-таблиц
<p>На удалённых серверах получаем промежуточные результаты,
разбитые на согласованные партиции.
Затем передаём партиции между серверами так,
чтобы на разных серверах были разные партиции,
Затем передаём партиции между серверами так,
чтобы на разных серверах были разные партиции,
а данные одной партиции оказались на одном сервере.
Мержим на всех серверах параллельно, да ещё и используя многие ядра.
@ -537,7 +537,7 @@ num_threads * num_buckets хэш-таблиц
Достоинства:
+ прекрасно масштабируется;
+ при INSERT SELECT, результат можно
вовсе не передавать на сервер-инициатор,
вовсе не передавать на сервер-инициатор,
а сразу сохранить в распределённую таблицу на кластере.
Недостатки:
@ -551,8 +551,8 @@ num_threads * num_buckets хэш-таблиц
<p style="font-size: 50px;">Можно задавать вопросы.</p>
</section>
<div class="progress"></div>
<script src="shower/shower.min.js"></script>
</body>

View File

@ -15,7 +15,7 @@
<section class="slide" id="cover">
<h1 style="margin-top: 200px">ClickHouse meetup<br/>в Санкт-Петербурге</h1>
</section>
<section class="slide">
<h2>ClickHouse: настоящее и будущее</h2>
</section>
@ -33,7 +33,7 @@
</section>
<section class="slide">
<h2>В предыдущих сериях</h2>
<p>&mdash; HTTP и executable источники;</p>
@ -136,7 +136,7 @@
<p>https://www.percona.com/blog/2017/02/13/clickhouse-new-opensource-columnar-database/</p>
<img src="pictures/spark.png" style="height:60%"/>
</section>
<section class="slide">
<h2>ClickHouse vs. Greenplum</h2>
<p><img src="pictures/greenplum.png" style="width:50%"/></p>

View File

@ -813,7 +813,7 @@ curl -sS 'http://localhost:8123/?max_result_bytes=4000000&amp;buffer_size=300000
- построение графиков, диаграмм и отображение геокоординат для результатов запросов;
- интерактивный конструктор сводных таблиц (pivot) для результатов запросов;
- графические средства для анализа состояния ClickHouse;
- два цветовых оформления: светлое и темное.
- два цветовых оформления: светлое и темное.
<a href="https://tabix.io/doc/">Документация Tabix</a>

View File

@ -12,7 +12,7 @@
* Не парсит JSON до конца (парсит только часть, необходимую для выполнения вызванного метода).
* Парсинг необходимой части запускается каждый раз при вызове методов.
* Может работать с обрезанным JSON-ом.
* При этом, (в отличие от SAX-подобных парсеров), предоставляет удобные методы для работы.
* При этом, (в отличие от SAX-подобных парсеров), предоставляет удобные методы для работы.
*
* Эта структура данных более оптимальна, если нужно доставать несколько элементов из большого количества маленьких JSON-ов.
* То есть, подходит для обработки "параметров визитов" и "параметров интернет магазинов" в Яндекс.Метрике.
@ -81,7 +81,7 @@ public:
};
ElementType getType() const;
bool isObject() const { return getType() == TYPE_OBJECT; };
bool isArray() const { return getType() == TYPE_ARRAY; };
bool isNumber() const { return getType() == TYPE_NUMBER; };
@ -138,7 +138,7 @@ public:
/// Класс JSON одновременно является итератором по самому себе.
using iterator = JSON;
using const_iterator = JSON;
iterator operator* () const { return *this; }
const JSON * operator-> () const { return this; }
bool operator== (const JSON & rhs) const { return ptr_begin == rhs.ptr_begin; }

View File

@ -1,7 +1,7 @@
#pragma once
/** Пример:
*
*
* class Derived : public Singleton<Derived>
* {
* friend class Singleton<Derived>;

View File

@ -183,7 +183,7 @@ JSON::ElementType JSON::getType() const
return TYPE_OBJECT;
case '[':
return TYPE_ARRAY;
case 't':
case 't':
case 'f':
return TYPE_BOOL;
case 'n':
@ -225,7 +225,7 @@ void JSON::checkPos(Pos pos) const
JSON::Pos JSON::skipString() const
{
//std::cerr << "skipString()\t" << data() << std::endl;
Pos pos = ptr_begin;
checkPos(pos);
if (*pos != '"')
@ -257,7 +257,7 @@ JSON::Pos JSON::skipString() const
if (*pos != '"')
throw JSONException(std::string("JSON: expected \", got ") + *pos);
++pos;
return pos;
}
@ -265,7 +265,7 @@ JSON::Pos JSON::skipString() const
JSON::Pos JSON::skipNumber() const
{
//std::cerr << "skipNumber()\t" << data() << std::endl;
Pos pos = ptr_begin;
checkPos(pos);
@ -292,10 +292,10 @@ JSON::Pos JSON::skipNumber() const
JSON::Pos JSON::skipBool() const
{
//std::cerr << "skipBool()\t" << data() << std::endl;
Pos pos = ptr_begin;
checkPos(pos);
if (*ptr_begin == 't')
pos += 4;
else if (*ptr_begin == 'f')
@ -310,7 +310,7 @@ JSON::Pos JSON::skipBool() const
JSON::Pos JSON::skipNull() const
{
//std::cerr << "skipNull()\t" << data() << std::endl;
return ptr_begin + 4;
}
@ -318,7 +318,7 @@ JSON::Pos JSON::skipNull() const
JSON::Pos JSON::skipNameValuePair() const
{
//std::cerr << "skipNameValuePair()\t" << data() << std::endl;
Pos pos = skipString();
checkPos(pos);
@ -327,14 +327,14 @@ JSON::Pos JSON::skipNameValuePair() const
++pos;
return JSON(pos, ptr_end, level + 1).skipElement();
}
JSON::Pos JSON::skipArray() const
{
//std::cerr << "skipArray()\t" << data() << std::endl;
if (!isArray())
throw JSONException("JSON: expected [");
Pos pos = ptr_begin;
@ -366,7 +366,7 @@ JSON::Pos JSON::skipArray() const
JSON::Pos JSON::skipObject() const
{
//std::cerr << "skipObject()\t" << data() << std::endl;
if (!isObject())
throw JSONException("JSON: expected {");
Pos pos = ptr_begin;
@ -374,7 +374,7 @@ JSON::Pos JSON::skipObject() const
checkPos(pos);
if (*pos == '}')
return ++pos;
while (1)
{
pos = JSON(pos, ptr_end, level + 1).skipNameValuePair();
@ -398,7 +398,7 @@ JSON::Pos JSON::skipObject() const
JSON::Pos JSON::skipElement() const
{
//std::cerr << "skipElement()\t" << data() << std::endl;
ElementType type = getType();
switch(type)
@ -618,7 +618,7 @@ std::string JSON::getString() const
case 'u':
{
Poco::UTF8Encoding utf8;
++s;
checkPos(s + 4);
std::string hex(s, 4);

View File

@ -36,7 +36,7 @@ static time_t orderedIdentifierToDate(unsigned value)
void loop(time_t begin, time_t end, int step)
{
const auto & date_lut = DateLUT::instance();
for (time_t t = begin; t < end; t += step)
{
time_t t2 = date_lut.makeDateTime(date_lut.toYear(t), date_lut.toMonth(t), date_lut.toDayOfMonth(t),
@ -44,9 +44,9 @@ void loop(time_t begin, time_t end, int step)
std::string s1 = toString(t);
std::string s2 = toString(t2);
std::cerr << s1 << ", " << s2 << std::endl;
if (s1 != s2)
throw Poco::Exception("Test failed.");
}

View File

@ -642,7 +642,7 @@ TEST(JSON_Suite, SimpleTest)
try
{
JSON j(r.input.c_str(), r.input.c_str() + r.input.size());
ASSERT_EQ(j.getString(), r.result);
ASSERT_TRUE(r.result_type == ResultType::Return);
}

View File

@ -20,18 +20,18 @@ public:
template <typename T> using KeyValuePair = std::pair<std::string, T>;
template <typename T> using KeyValueVector = std::vector<KeyValuePair<T>>;
template <typename T> void write(const std::string & key, const T & value,
template <typename T> void write(const std::string & key, const T & value,
time_t timestamp = 0, const std::string & custom_root_path = "")
{
writeImpl(KeyValuePair<T>{ key, value }, timestamp, custom_root_path);
}
template <typename T> void write(const KeyValueVector<T> & key_val_vec,
template <typename T> void write(const KeyValueVector<T> & key_val_vec,
time_t timestamp = 0, const std::string & custom_root_path = "")
{
writeImpl(key_val_vec, timestamp, custom_root_path);
}
/// возвращает путь root_path.server_name
static std::string getPerServerPath(const std::string & server_name, const std::string & root_path = "one_min");
private:
@ -60,7 +60,7 @@ private:
template <typename T>
void out(std::ostream & os, const KeyValuePair<T> & key_val, time_t timestamp, const std::string & custom_root_path)
{
os << (custom_root_path.empty() ? root_path : custom_root_path) <<
os << (custom_root_path.empty() ? root_path : custom_root_path) <<
'.' << key_val.first << ' ' << key_val.second << ' ' << timestamp << '\n';
}

View File

@ -12,7 +12,7 @@ class Query;
/** Базовый класс для UseQueryResult и StoreQueryResult.
* Содержит общую часть реализации,
* Содержит общую часть реализации,
* Ссылается на Connection. Если уничтожить Connection, то пользоваться ResultBase и любым результатом нельзя.
* Использовать объект можно только для результата одного запроса!
* (При попытке присвоить объекту результат следующего запроса - UB.)

View File

@ -12,15 +12,15 @@ StoreQueryResult::StoreQueryResult(MYSQL_RES * res_, Connection * conn_, const Q
UInt32 fields = getNumFields();
reserve(rows);
lengths.resize(rows * fields);
for (UInt64 i = 0; MYSQL_ROW row = mysql_fetch_row(res); ++i)
{
MYSQL_LENGTHS lengths_for_row = mysql_fetch_lengths(res);
memcpy(&lengths[i * fields], lengths_for_row, sizeof(lengths[0]) * fields);
push_back(Row(row, this, &lengths[i * fields]));
}
checkError(conn->getDriver());
}
}

View File

@ -16,7 +16,7 @@ class Foundation_API LevelFilterChannel: public Channel
public:
void log(const Message& msg);
/// Sends the given Message to all
/// attaches channels.
/// attaches channels.
void setProperty(const std::string& name, const std::string& value);
/// Sets or changes a configuration property.
@ -24,7 +24,7 @@ public:
/// Only the "level" property is supported, which allows setting desired level
void setChannel(Channel* pChannel);
/// Sets the destination channel to which the formatted
/// Sets the destination channel to which the formatted
/// messages are passed on.
Channel* getChannel() const;
@ -33,10 +33,10 @@ public:
void open();
/// Opens the attached channel.
void close();
/// Closes the attached channel.
void setLevel(Message::Priority);
/// Sets the Logger's log level.
void setLevel(const std::string& value);

View File

@ -1,29 +1,29 @@
//
//
// LevelFilterChannel.cpp
//
//
// $Id$
//
//
// Library: Ext
// Package: Logging
// Module: LevelFilterChannel
//
//
// Copyright (c) 2004-2007, Applied Informatics Software Engineering GmbH.
// and Contributors.
//
//
// Permission is hereby granted, free of charge, to any person or organization
// obtaining a copy of the software and accompanying documentation covered by
// this license (the "Software") to use, reproduce, display, distribute,
// execute, and transmit the Software, and to prepare derivative works of the
// Software, and to permit third-parties to whom the Software is furnished to
// do so, all subject to the following:
//
//
// The copyright notices in the Software and this entire statement, including
// the above license grant, this restriction and the following disclaimer,
// must be included in all copies of the Software, in whole or in part, and
// all derivative works of the Software, unless such copies or derivative
// works are solely in the form of machine-executable object code generated by
// a source language processor.
//
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
@ -70,7 +70,7 @@ void LevelFilterChannel::open()
_channel->open();
}
void LevelFilterChannel::close()
{
if (_channel)

View File

@ -4,7 +4,7 @@
namespace zkutil
{
class Increment
{
public:
@ -13,15 +13,15 @@ public:
{
zookeeper_holder->getZooKeeper()->createAncestors(path);
}
size_t get()
{
LOG_TRACE(log, "Get increment");
size_t result = 0;
std::string result_str;
zkutil::Stat stat;
bool success = false;
auto zookeeper = zookeeper_holder->getZooKeeper();
do
@ -37,7 +37,7 @@ public:
}
}
while (!success);
return result;
}
private:

View File

@ -8,7 +8,7 @@ int main()
{
auto zookeeper_holder = std::make_shared<zkutil::ZooKeeperHolder>();
zookeeper_holder->init("localhost:2181");
zkutil::Lock l(zookeeper_holder, "/test", "test_lock");
std::cout << "check " << l.tryCheck() << std::endl;
std::cout << "lock tryLock() " << l.tryLock() << std::endl;