senconscious

senconscious

What is the optimal --max-requires option for tests?

Hello everyone,
I have encountered a strange bottleneck when trying to run tests. The execution time of specific tests was increasing according to the number of schedulers online: each scheduler added about 100ms to the execution time.

CI Setup

I’m running CI tests using a GitLab runner on Amazon EC2 c6g instances. The runner has 32 CPUs.

Local Setup

8 CPUs, Mac M1.

Test Details

I have 2 partitions for tests, each with about 3.5k tests. Running the command:

MIX_TEST_PARTITION=1 elixir --erl "+S 8:8" -S mix test --partitions 2

The unstable test uses the test_server library to open a socket on a random port with plug_cowboy. There are no heavy computations inside the mocked request; it just responds with a hardcoded small JSON map. Two subsequent requests are made.

From the client side, I’m using Finch with Mint, with a pool size of 10.

Test Running Time

Below are the execution times for the unstable test when running locally on 8 CPUs:

| Single       | 20ms  |
|--------------|-------|
| During suite | 800ms |

I then experimented with the number of schedulers:

| 1 scheduler  | ~100ms |
|--------------|--------|
| 2 schedulers | ~200ms |
| 3 schedulers | ~300ms |
| 8 schedulers | ~800ms |

Telemetry

To find the cause, I attached telemetry to finch and cowboy:

finch.queue.stop duration: 388ms : idle time: 0ms
finch.connect.stop duration: 982ms
finch.send.stop duration: 395ms : idle time: 0ms
cowboy.request.stop duration: 1916ms : req_body_duration: 0ms : resp_duration: 0ms
finch.recv.stop duration: 3248ms : idle time: 0ms
finch.request.stop duration: 5608ms

Given that no work is done inside dispatching except Plug.Conn.send_resp/3, this seemed very strange.

Running fprof

{ suspend,                                      70,  680.139,    0.000},     %
 [ ]}.

{[{{error_handler,undefined_function,3},          1,  659.626,    0.003},      
  {{'Elixir.Acme.Operations.SF.IN.SyncServiceContracts',
    request_page,2},   1,   10.840,    0.002}],     

....


 { {code_server,call,1},                         30,  383.299,    0.411},     %
 [{suspend,                                      33,  382.695,    0.000},      
  {{erlang,demonitor,2},                         30,    0.152,    0.119},      
  {{erlang,monitor,2},                           30,    0.041,    0.041}]}.    

{[{{error_handler,undefined_function,3},         19,  360.224,    0.044}],     

These are the most expensive nodes in the whole fprof logs. It seems the process gets descheduled and was suspended most of the time while code was loading into the memory inside Mix.Compilers.Test

Researching Similar Issue

After a while, I found a discussion and tried explicitly setting the max-requires option. It turns out that on 8 CPUs, the test ran in less than 100ms with max-requires set to 100. In Elixir core, it defaults to the maximum between the system schedulers online and 2.

However, the docs lack details about how this parameter can affect test execution time. Maybe someone can help explain the algorithm for calibrating it?

Where Next?

Popular in Questions Top

Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New
shahryarjb
Hello, I get Persian date from my client and convert it to normal calendar like this: def jalali_string_to_miladi_english_number(persi...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
ycv005
I have followed this StackOverflow post to install the specific version of Erlang. And When I am running mix ecto.setup then getting fol...
New
polypush135
As many of you may have realized by now (sorry for all the posts here) I’ve been working on a db problem where I’m trying to aggregate a ...
New
gazoon
I want to know absolute current module path. In python i could do that: os.path.abspath(__file__) Does elixir have anything similar?
New
vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
script
If I have a string “1000 cfu/ml” . I want to remove the characters and / and space . So the string is like this "1000" What is the ...
New
mgjohns61585
Could someone help me? I'm making my first elixir program, number guessing game. I can't figure out how to convert the user's guess from ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New

Other popular topics Top

Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID<0.412.0> terminating ** (Postgrex.Error) FATAL...
New
chrisalley
ExUnit now has describe blocks which is a welcome addition coming from RSpec. In the docs, it states that nested hierarchies of describe ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
jerry
Good day to you all. I have been struggling to get a query involving like and ilike to work. Can anyone assist me on this, please? pro...
New
New
chrismccord
This release brings a number of exciting features, including integration with the new Phoenix LiveDashboard and Phoenix LiveView. There h...
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
ashish173
I am using Ecto timestamps with postgres, I can see the timestamps() use the :naive_dateime but for my use case I wanted to store the ti...
New
baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New

We're in Beta

About us Mission Statement