          warnings,
          %{schedulers: schedulers} = state
        )
-       when map_size(spawned) - length(waiting) >= schedulers do
+       when map_size(spawned) - map_size(waiting) >= schedulers do
     wait_for_messages(queue, spawned, waiting, files, result, warnings, state)
   end
 
   # Release waiting processes
-  defp spawn_workers([{ref, found} | t], spawned, waiting, files, result, warnings, state) do
+  defp spawn_workers([{pid, found} | t], spawned, waiting, files, result, warnings, state) do
     {files, waiting} =
-      case List.keytake(waiting, ref, 2) do
-        {{_kind, pid, ^ref, file_pid, _on, _defining, _deadlock}, waiting} ->
+      case Map.pop(waiting, pid) do
+        {{_kind, ref, file_pid, _on, _defining, _deadlock}, waiting} ->
           send(pid, {ref, found})
           {update_timing(files, file_pid, :waiting), waiting}
 
-        nil ->
+        {nil, waiting} ->
           # In case the waiting process died (for example, it was an async process),
           # it will no longer be on the list. So we need to take it into account here.
           {files, waiting}

          wait_for_messages(queue, new_spawned, waiting, new_files, result, warnings, state)
        end
    end
  end

  defp update_timing(files, pid, key) do


      {:available, kind, module} ->
        available =
          for {pid, {^kind, _, _, ^module, _defining, _deadlock}} <- waiting,
              do: {pid, :found}

        result = Map.put(result, {kind, module}, true)
        spawn_workers(available ++ queue, spawned, waiting, files, result, warnings, state)
