Почему мои тесты Minitest не выполняются параллельно?

Я только недавно понял, что мои тесты Minitest могут работать параллельно. Все, что мне нужно было сделать, это

require "minitest/hell"

и я так и сделал. К сожалению, мои тесты работают так же, как и раньше. Все проходит, и это занимает ровно столько времени, сколько обычно. Я проверил htop во время работы моего набора тестов, и используется только одно ядро.

Я установил точку останова в случайном тесте, чтобы проверить, были ли тесты настроены на параллельное выполнение:

(byebug) Minitest:: Test.test_order:параллельно

Так, что происходит?


Моим первым предположением было то, что Minitest подсчитывает количество ядер ЦП, когда решает, сколько процессов порождать. У меня было несколько физических процессоров (на виртуальной машине), но по одному ядру на процессор. Я изменил свой VPS, чтобы иметь два физических процессора, каждый с 4 ядрами, и мои тесты все еще не выполняются параллельно.

$ lscpu
Архитектура:          x86_64
Операционные режимы процессора:        32-разрядный, 64-разрядный
Порядок байтов:            Little Endian
ЦП:                8
Он-лайн список процессоров:   0-7
Резьба (ы) на ядро:    1
Сердечник (и) на сокет:    4
Разъем (ы):             2
NUMA узел (ы):          1
Идентификатор поставщика:             GenuineIntel
Семейство процессоров:            6
Модель:                 62
Степпинг:    4
МГц процессора:               2600.000
BogoMIPS:              5200,00
Поставщик гипервизора:     VMware
Тип виртуализации: полная
L1d кеш:             32K
L1i кеш: 32K
Кэш-память второго уровня:              256 КБ
Кэш-память третьего уровня:              20480 КБ
NUMA узел0 ЦП:   0-7

3 ответа

Решение

Minitest использует потоки, а не процессы для параллельного выполнения теста.

Поскольку MRI (стандартный интерпретатор Ruby) имеет глобальную блокировку интерпретатора, одновременно может выполняться только один поток. Поэтому ваши тесты не работают параллельно при использовании МРТ.

Вы можете настроить параллельное выполнение тестов с помощью интерпретатора Ruby, который поддерживает параллельные потоки, такие как JRuby или Rubinius.

Прочтите эту статью для более подробной информации.

Ответ Северина о том, что МРТ не может выполняться параллельно из-за GIL, является правильным. (Отказ от ответственности: я написал статью, на которую он ссылается.) Во многих рецензиях язык становится немного размытым, но вы можете прочитать эту статью для очень простого описания.

Если вы по-прежнему заинтересованы в параллельном выполнении тестов и не можете изменить интерпретаторы Ruby, взгляните на гем parallel_tests в качестве альтернативы, хотя и с некоторыми ограничениями.

Для параллельного запуска тестов вам нужна либо версия Ruby, которая обеспечивает параллельное выполнение (например, JRuby), либо вы можете использовать простые команды оболочки для запуска нескольких запусков minitest.

Например, используйте GNU параллельно:

find test -type f | parallel --dry-run  bundle exec rake test TEST={}

(The dry-run флаг, чтобы вы могли видеть, что происходит, прежде чем запустить его; опустить dry-run Отметьте, когда вы удовлетворены, команды будут делать то, что вы хотите.)

Накладные расходы на bundle exec и rake очень высоки. Основное преимущество параллельного выполнения состоит в том, чтобы гарантировать, что ваши тесты ведут себя правильно - то есть основное преимущество не в скорости. Если вы используете параллельный, вы, вероятно, захотите попробовать spork который держит предварительно разогретое приложение готовым.

Другие вопросы по тегам