Scala: модульное / интеграционное тестирование параллельной обработки для понимания
У меня есть проект Play, который использует для понимания для параллельного выполнения задач. Допустим, нам дают код ниже. Я хочу проверить, что функция firstF и secondF фактически выполняется параллельно. Что было бы лучшим способом проверить это? Я думал об утверждении, что время начала и окончания перекрываются, но мог бы быть лучший способ проверить это.
def async = Action.async {
val firstF = future{
val s = "start: " + new java.util.Date().toString() + " :: "
Thread.sleep(1000)
val e = "end: " + new java.util.Date().toString()
"First function: " + s + e + "\n\n"
}
val secondF = future{
val s = "start: " + new java.util.Date().toString() + " :: "
Thread.sleep(1000)
val e = "end: " + new java.util.Date().toString()
"Second function: " + s + e + "\n\n"
}
val result = for {
fContent <- firstF
sContent <- secondF
} yield fContent + sContent
result map {
x => Ok( x )
}
}
1 ответ
РЕДАКТИРОВАТЬ:
Для проверки времени выполнения какого-либо выполнения стандартным способом является использование инфраструктуры ScalaMeter для регрессионного тестирования производительности.
val gen = Gen.range("times")(1000, 2000, 500)
performance of "Futures" in {
using(gen) in { time =>
val f: Future[Unit] = runningFor(time) // returns some future that takes time milliseconds to execute
Await.ready(f)
}
}
Смотрите полный пример "Начало работы" здесь.
Ручной метод:
Вы можете напечатать название текущей темы, используя Thread.currentThread.getName
, В стандарте ExecutionContext
реализация, это напечатает имена рабочих потоков fork/join. Если имена для двух будущих вычислений будут разными, это хороший признак того, что они выполняются параллельно.
В противном случае вы можете попробовать синхронизировать начало и конец фьючерса, используя System.currentTimeMillis
и сравнение, если два интервала перекрываются.
Наконец, в вашем примере каждое будущее занимает много времени. Если программа завершается через 1 секунду, они, очевидно, выполняются параллельно. Если программа завершается через 2 секунды, два фьючерса выполняются последовательно, потому что ExecutionContext
использует только один поток.
Обратите внимание, что, Thread.sleep
это длительная операция блокировки, которая блокирует рабочий поток. Как правило, используйте blocking
директива вокруг операций блокировки, чтобы разрешить изменение размера пула рабочих потоков при необходимости:
Future { // note: lowercase `future` has been deprecated, use uppercase
blocking {
Thread.sleep(1000)
}
}