Как стать автором
Обновить

Комментарии 14

В поддерживаемые БД можно добавить MongoDB.
MongoDB and NUMA, Non-Uniform Access Memory, do not work well together. When running MongoDB on NUMA hardware, disable NUMA for MongoDB and running with an interleave memory policy. NUMA can cause a number of operational problems with MongoDB, including slow performance for periods of time or high system processor usage.

docs.mongodb.org/manual/administration/production-notes/#production-numa

Ну я бы так не сказал.
Судя по тестам, работает одинаково — что с отключенным NUMA, что со включенным.
Хотя, может это как раз и есть тот случай, о котором писал автор:
продукт, не поддерживающий NUMA, то есть, просто не знающий о ней, что совсем не мешает ему запускаться и исполняться на NUMA-системах, покажет не худшую производительность, чем официально поддерживающий NUMA
Пара замечаний.

malloc в VC рантайме — это очень тонкий слой над HeapAlloc (_malloc_base->_heap_alloc->HeapAlloc), который в свою очередь является субаллокатором над VirtualAlloc (VirtualAlloc умеет выделять только страницами, а Heap Manager затем «нарезает» эти страницы на блоки меньшего размера по требованию клиента). В данном случае единственное существенное отличие от Linux в том, что Windows память коммитит, а Linux — оверкоммитит (по умолчанию).

Простейший тест:
#include <Windows.h>
#include <psapi.h>
#include <memory.h>
#include <stdio.h>

int
main() {
	PROCESS_MEMORY_COUNTERS pmc = {};

	GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
	printf("WS: %d\tPeak WS: %d\tCommit: %d\tPeak commit: %d\n", pmc.WorkingSetSize, pmc.PeakWorkingSetSize, pmc.PagefileUsage, pmc.PeakPagefileUsage);

	auto mem = malloc(1024 * 1024 * 1024);
	printf("malloc(1Gb) - %s\n", (mem != nullptr) ? "check" : "uncheck");

	ZeroMemory(&pmc, sizeof(pmc));
	GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
	printf("WS: %d\tPeak WS: %d\tCommit: %d\tPeak commit: %d\n", pmc.WorkingSetSize, pmc.PeakWorkingSetSize, pmc.PagefileUsage, pmc.PeakPagefileUsage);

	if (mem != nullptr) {
		free(mem);
		mem = nullptr;
		printf("Fre-e-e-e-e-edom\n");

		ZeroMemory(&pmc, sizeof(pmc));
		GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc));
		printf("WS: %d\tPeak WS: %d\tCommit: %d\tPeak commit: %d\n", pmc.WorkingSetSize, pmc.PeakWorkingSetSize, pmc.PagefileUsage, pmc.PeakPagefileUsage);
	}
}


выдает следующее:
Current: 1445888	Peak: 1445888	Commit: 315392	Peak commit: 315392
malloc(1Gb) - check
Current: 3588096	Peak: 3588096	Commit: 1076162560	Peak commit: 1076162560
Fre-e-e-e-e-edom
Current: 1482752	Peak: 3588096	Commit: 315392	Peak commit: 1076162560


Как минимум в Windows affinity mask на процессе или потоке является обязательной к «исполнению». То есть поток всегда планируется ТОЛЬКО на процессорах, входящих в маску/группу.

Измерения проводились на HP ProLiant 360 G7 с двумя Intel Xeon X5690

Как видите, разница составляет всего чуть более 5%! Результат приятно удивительный. И это – случай максимальной разницы, достигаемый при 32 одновременно работающих потоках с запросами

Просто хочу уточнить, этот случай является худшим только с точки зрения самого теста (100% local vs 100% remote, не совсем понимаю при чем здесь количество потоков — наверное я что-то упускаю из виду). Все таки два Xeon-а в одном пакете — это далеко не худший случай с т.з. тестового окружения. На больших блейдах скорость доступа может отличаться в разы или даже на порядок.
про malloc — да, все так, как вы пишете, но я не вижу противоречий со своими утверждениями.

Про потоки — я тоже не понимаю, как влияет их число на данный тест, (скорее всего, это особенности реализации SQL, с которыми я не знакома). Но не понимаю, почему будут сильные ухудшения на больших блейдах в этом случае (используются 2 узла).
> Но надо понимать, что во-первых, affinity срабатывает не всегда (для системы это, скорее, намек, чем приказ)…

Вы это про какую «систему» говорите? Я почему-то, за всю свою практику, ни разу не сталкивался со случаем «несработавшего» affinity ;)

Я сталкивалась. Но не в Win API, а в библиотеках, где есть ф-и для установки привязки к ЦПУ. А так как я говорю «в общем», а не про конкретную систему, то оно — так.
NUMA дебютировала в архитектуре Nehalem сначала в десктопной версии Core i7, а уж потом в Xeon:
Nehalem-based_Xeon

The first processor released with the Nehalem architecture is the desktop Intel Core i7, which was released in November 2008


Поддержка NUMA реализована и в Java SE 6u2, JVM 1.6


JVM 1.6 это что?
Автор статьи забыла упомянуть что Intel в переходе на NUMA был в роли догоняющего, что в процессорах AMD NUMA появилась гораздо раньше.
У меня на столе стоит именно такая машина — desktop Intel Core i7 с NUMA. Но я на 99% уверена, что такие машины не продавались, официальные продажи начались с Xeon.
JVM 1.6 — это Oracle JVM.

Упомянуть про AMD я не забыла, а специально предоставила такую возможность комментаторам. Вы ей воспользовались.
В Core i7 системах была только одна NUMA node, поэтому вся память там локальная. Чтобы прочувствовать все проблемы NUMA требуется хотя бы двухпроцессорная конфигурация.
У меня сложилось несколько другое представление о степени воздействия NUMA на производительность приложения. При работе с вычислительными задачами мы сталкивались с двухразовым изменением производительности. Даже простое однопоточное приложение запущенное на вычислительных системах с NUMA показывает очень нестабильное поведение из-за того, что может перейти на вычислительное ядро другого сокета. Изменение производительности на 10-15 процентов довольно распространенная ситуация. И действительно, приходится использовать установку affinity чтобы получать более-менее стабильные цифры.
Мое изначальное представление тоже было похожим — 10-15% в идеале, и до двух раз в худшем случае. Но сомневаться в результатах из поста у меня оснований нет. Возможные их объяснения — хорошая железная реализация NUMA (удаленная память медленнее всего на 20-30%), отсутствие синхронизации кешей и записи в память, а главное, сама структура SQL, в которой основное время тратится не на доступ к памяти, а на что-то другое.
Но, несмотря на это, толковых статей, объясняющих, что это, а главное, как с этим эффективно работать, нет


Позвольте не согласиться, а как же уже упомянутый в комментариях Ulrich Drepper с его статьей What Every Programmer Should Know About Memory (также есть ее перевод на русский язык). На мой взгляд он довольно не плохо рассказывает про основы NUMA и библиотеку libnuma (конечно про Windows там ни чего не упоминается).
Зарегистрируйтесь на Хабре, чтобы оставить комментарий