Я работаю над настройкой производительности на высокопроизводительном высокопроизводительном механизме данных, который в конечном итоге обслуживает конечных пользователей.В частности, делегированная мне часть вращается вокруг характеристики многопоточного ввода-вывода файлов и отображения памяти данных в локальный кеш.При написании тестовых приложений для изоляции временных столбов было выявлено несколько вопросов.Код был свернут для выполнения только вызова открытия системного файла (open(O_RDONLY)
).Я надеюсь, что результат этого запроса поможет нам понять фундаментальные системные процессы низкого уровня, чтобы можно было понять полную прогнозирующую (или, по крайней мере, реляционную) временную модель.Предложения всегда приветствуются.Кажется, мы достигли временного барьера и хотели бы понять поведение и определить, можно ли его преодолеть.
Тестовая программа:
- Написана на C,скомпилирован с использованием компилятора gnu C, как указано ниже;
- записывается минимально для изоляции обнаруженных проблем в один системный файл «open ()»;
- настраивается для одновременного запуска запрошенного числаpthreads;
- загружает список из 1000 текстовых файлов размером ~ 8K;
- создает потоки (просто) без изменений атрибутов;
- каждый поток выполняет несколько последовательных файловopen () вызывает следующий доступный файл из заранее определенного списка файлов, пока список файлов не будет исчерпан таким образом, что один поток должен открыть все 1000 файлов, 2 потока теоретически должны открыть 500 файлов (пока не доказано) и т. д.);
Мы проводили тесты несколько раз, параметрически изменяя количество потоков, размеры файлов и наличие файлаs расположены на локальном или удаленном сервере.Возникло несколько вопросов.
Наблюдаемые результаты (открытие удаленных файлов):
- Время открытия файла выше с первого раза (как и ожидалось, из-за кэширования файла);
- Запуск тестового приложения с одним потоком для загрузки всех удаленных файлов занимает X секунд;
- Похоже, что запуск приложения с числом потоков от 1 до # доступных процессоров на машине приводит к увеличению временипропорциональны количеству процессоров (nX секунд).
- Запуск приложения с использованием счетчика потоков> #CPUs приводит к тому, что время выполнения выровняется примерно на то же значение, что и время, необходимое для запускас потоками #CPU (это случайный или систематический лимит, или что?).
- Запуск нескольких параллельных процессов (например, 25 одновременных экземпляров одного и того же тестового приложения) приводит к тому, что время становится приблизительно линейнымс числом процессов для выбранного количества потоков.
- Запуск приложения на разных серверах показывает аналогичные результаты
Наблюдаемые результаты (открытие файлов, находящихся локально):
- На несколько порядков быстрее (как и следовало ожидать);
- При увеличении числа потоков возникает НИЗКАЯ точка перегиба синхронизациипримерно 4-5 активных потоков, затем снова увеличивается до тех пор, пока число потоков не станет равным количеству ЦП, а затем снова выравнивается;
- Запуск нескольких параллельных процессов (один и тот же тест) приводит к тому, что время становится приблизительно линейным с числомпроцессов с постоянным числом потоков (тот же результат, что и выше # 5).
Кроме того, мы заметили, что локальные открытия занимают около 0,01 мс, а последовательные открытия сети в 100 раз медленнее при 1 мс.Открывая сетевые файлы, мы получаем линейное увеличение пропускной способности до 8 раз с 8 потоками, но 9+ потоков ничего не делают.Похоже, что открытые вызовы сети блокируются после более чем 8 одновременных запросов.То, что мы ожидали, было начальной задержкой, равной сетевой передаче туда и обратно, а затем приблизительно такой же пропускной способностью, что и локальной.Возможно, в локальных и удаленных системах выполняется дополнительная блокировка мьютекса, которая занимает в 100 раз больше времени.Возможно, существует какая-то внутренняя очередь удаленных вызовов, которая содержит только 8.
ОжидайтеРезультаты и вопросы, на которые нужно ответить либо тестом, либо ответами на форумах, подобных этому:
- Запуск нескольких потоков приведет к выполнению той же самой работы за более короткое время;
- Есть лиоптимальное количество потоков;
- Существует ли связь между количеством доступных потоков и процессоров?
- Существует ли какая-то другая систематическая причина, по которой наблюдается ограничение в 8-10 файлов?
- Как работает системный вызов open () в многопоточном процессе?
- Каждый поток получает свой временной интервал с переключением контекста;
- Блокирует ли вызов open () и ждет ли файл открытия / загрузки в файловый кеш?Или вызов разрешает переключение контекста во время выполнения операции?
- Когда open () завершается, планировщик перераспределяет этот поток, чтобы выполнить его раньше, или поток должен ждать до своего поворота вциклический способ;
- Будет ли иметь значение изменение монтированного тома, на котором находятся 1000 файлов, доступного только для чтения или чтения / записи?
- Когда open () вызывается с полнымпуть, каждый элемент в пути stat () ed?Имеет ли смысл открывать () общий каталог в дереве списка файлов, а затем открывать () файлы в этом общем каталоге по относительному пути?
Настройка теста разработки:
Red Hat Enterprise Linux Server release 5.4 (Tikanga)
8-CPUS, each with characteristics as shown below:
processor : 0
vendor_id : GenuineIntel
cpu family : 6
model : 23
model name : Intel(R) Xeon(R) CPU X5460 @ 3.16GHz
stepping : 6
cpu MHz : 1992.000
cache size : 6144 KB
physical id : 0
siblings : 4
core id : 1
cpu cores : 4
apicid : 1
fpu : yes
fpu_exception : yes
cpuid level : 10
wp : yes
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush dts acpi mmx fxsr sse sse2 ss ht tm syscall lm constant_tsc pni monitor ds_cpl vmx est tm2 ssse3 cx16 xtpr sse4_1 lahf_lm
bogomips : 6317.47
clflush size : 64
cache_alignment : 64
address sizes : 38 bits physical, 48 bits virtual
power management:
GNU C compiler, version:
gcc (GCC) 4.1.2 20080704 (Red Hat 4.1.2-46)