Skip to content

Commit d800e9c

Browse files
committed
Parallelize log dispatch on CaptureLog, closes #14288
1 parent 2cd752c commit d800e9c

File tree

1 file changed

+22
-11
lines changed

1 file changed

+22
-11
lines changed

lib/ex_unit/lib/ex_unit/capture_server.ex

+22-11
Original file line numberDiff line numberDiff line change
@@ -231,18 +231,29 @@ defmodule ExUnit.CaptureServer do
231231
## :logger handler callback.
232232

233233
def log(event, _config) do
234-
for {_ref, string_io, level, formatter_mod, formatter_config} <- :ets.tab2list(@ets),
235-
:logger.compare_levels(event.level, level) in [:gt, :eq] do
236-
chardata = formatter_mod.format(event, formatter_config)
237-
# There is a race condition where the capture_log is removed
238-
# but another process is attempting to log to string io device
239-
# that no longer exists, so we wrap it in try/catch.
240-
try do
241-
IO.write(string_io, chardata)
242-
rescue
243-
_ -> :ok
234+
:ets.tab2list(@ets)
235+
|> Enum.filter(fn {_ref, _string_io, level, _formatter_mod, _formatter_config} ->
236+
:logger.compare_levels(event.level, level) in [:gt, :eq]
237+
end)
238+
|> Enum.group_by(
239+
fn {_ref, _string_io, _level, formatter_mod, formatter_config} ->
240+
{formatter_mod, formatter_config}
241+
end,
242+
fn {_ref, string_io, _level, _formatter_mod, _formatter_config} ->
243+
string_io
244244
end
245-
end
245+
)
246+
|> Enum.map(fn {{formatter_mod, formatter_config}, string_ios} ->
247+
Task.async(fn ->
248+
chardata = formatter_mod.format(event, formatter_config)
249+
250+
# Simply send, do not wait for reply
251+
for string_io <- string_ios do
252+
send(string_io, {:io_request, self(), make_ref(), {:put_chars, :unicode, chardata}})
253+
end
254+
end)
255+
end)
256+
|> Task.await_many(:infinity)
246257

247258
:ok
248259
end

0 commit comments

Comments
 (0)