#!/usr/bin/env escript %% -*- mode: erlang -*- %%! -pa ranch/ebin -sname ranch_race +P 1000000 +A 200 +K true -env ERL_MAX_PORTS 1000000 %% This script is tested only in Linux environment. %% I could not make it work with Mac OS (it limits connection rate). %% %% Warning: you are likely going to hit max open files limit. %% Before running this script you should raise max fds by executing: %% sudo -E -- bash -c "ulimit -n 1000000; sudo -E -u $USER bash --login" -module(ranch_race). -mode(compile). -export([main/1]). -export([stress_worker/1]). %-behaviour(ranch_protocol). -export([start_link/4]). %-behaviour(gen_server). -export([init/1, handle_info/2, terminate/2]). %% escript entry function main([]) -> start_stress(2000), receive stop -> exit({shutdown, stopped}) end. start_stress(WorkerCount) -> {ok, Port} = start_listener(), _ = [spawn_link(?MODULE, stress_worker, [Port]) || _ <- lists:seq(1, WorkerCount)], ok. start_listener() -> application:load(sasl), application:set_env(sasl, errlog_type, error), application:ensure_all_started(sasl), application:ensure_all_started(ranch), {ok, _} = ranch:start_listener(?MODULE, 1000, ranch_tcp, [{port, 0}, {max_connections, infinity}, {reuseaddr, true}], ?MODULE, []), {ok, ranch:get_port(?MODULE)}. stress_worker(Port) -> {ok, S} = gen_tcp:connect("localhost", Port, [{active, false}, {reuseaddr, true}]), gen_tcp:close(S), ?MODULE:stress_worker(Port). %%% Ranch protocol based on gen_server like described at http://ninenines.eu/docs/en/ranch/HEAD/guide/protocols/ start_link(Ref, Socket, Transport, _Opts) -> gen_server:start_link(?MODULE, [Ref, Socket, Transport], []). init([Ref, Socket, Transport]) -> {ok, {state, Ref, Socket, Transport}, 0}. handle_info(timeout, State={state, Ref, _Socket, _Transport}) -> ok = ranch:accept_ack(Ref), {stop, {shutdown, got_timeout}, State}; handle_info(Message, State) -> io:format("Got unexpected message: ~120p~n", [Message]), {stop, {shutdown, unexpected_message}, State}. terminate(_, _) -> ok.