@@ -157,14 +157,18 @@ class WebSocketSession : public std::enable_shared_from_this<WebSocketSession>,
157157 WebViewerHook* viewer_hook_ = nullptr ;
158158 std::size_t viewer_token_ = 0 ;
159159
160+ // In-flight request window announced to the client on connect.
161+ int max_in_flight_ = 16 ;
162+
160163 public:
161164 WebSocketSession (Tcp::socket&& socket,
162165 std::shared_ptr<TileGenerator> generator,
163166 std::shared_ptr<TclEvaluator> tcl_eval,
164167 std::shared_ptr<TimingReport> timing_report,
165168 std::shared_ptr<ClockTreeReport> clock_report,
166169 utl::Logger* logger,
167- WebViewerHook* viewer_hook);
170+ WebViewerHook* viewer_hook,
171+ int max_in_flight);
168172 ~WebSocketSession ();
169173
170174 void run (http::request<http::string_body>&& req);
@@ -223,7 +227,8 @@ WebSocketSession::WebSocketSession(
223227 std::shared_ptr<TimingReport> timing_report,
224228 std::shared_ptr<ClockTreeReport> clock_report,
225229 utl::Logger* logger,
226- WebViewerHook* viewer_hook)
230+ WebViewerHook* viewer_hook,
231+ int max_in_flight)
227232 : websocket_(std::move(socket)),
228233 logger_ (logger),
229234 select_handler_(generator, tcl_eval),
@@ -234,7 +239,8 @@ WebSocketSession::WebSocketSession(
234239 drc_handler_(generator),
235240 strand_(net::make_strand(websocket_.get_executor())),
236241 generator_(std::move(generator)),
237- viewer_hook_(viewer_hook)
242+ viewer_hook_(viewer_hook),
243+ max_in_flight_(max_in_flight)
238244{
239245 if (generator_) {
240246 odb::dbChip* chip = generator_->getChip ();
@@ -433,25 +439,15 @@ void WebSocketSession::on_accept(beast::error_code ec)
433439
434440 // Tell the client how many requests to keep in flight at once. This bounds
435441 // the client's send rate so a burst of tile requests (rapid pan/zoom) can't
436- // flood the socket send buffer and wedge the connection. Scale with the
437- // machine size — a larger box can absorb more concurrency — and clamp to a
438- // sane range. Sent first so the client has it before requesting any tiles.
442+ // flood the socket send buffer and wedge the connection. The limit is scaled
443+ // to the server's I/O worker count (see WebServer::serve). Sent first so the
444+ // client has it before requesting any tiles.
439445 {
440- unsigned int cores = std::thread::hardware_concurrency ();
441- if (cores == 0 ) {
442- cores = 4 ; // hardware_concurrency may report 0; pick a modest default
443- }
444- int max_in_flight = static_cast <int >(cores) * 4 ;
445- if (max_in_flight < 16 ) {
446- max_in_flight = 16 ;
447- } else if (max_in_flight > 256 ) {
448- max_in_flight = 256 ;
449- }
450446 WebSocketResponse cfg;
451447 cfg.id = 0 ;
452448 cfg.type = WebSocketResponse::kJson ;
453449 const std::string cfg_json = R"( {"type":"config","max_in_flight":)"
454- + std::to_string (max_in_flight ) + " }" ;
450+ + std::to_string (max_in_flight_ ) + " }" ;
455451 cfg.payload .assign (cfg_json.begin (), cfg_json.end ());
456452 queue_response (cfg);
457453 }
@@ -749,6 +745,7 @@ class DetectSession : public std::enable_shared_from_this<DetectSession>
749745 http::request<http::string_body> req_;
750746 utl::Logger* logger_;
751747 WebViewerHook* viewer_hook_ = nullptr ;
748+ int max_in_flight_ = 16 ;
752749
753750 public:
754751 DetectSession (Tcp::socket&& socket,
@@ -757,7 +754,8 @@ class DetectSession : public std::enable_shared_from_this<DetectSession>
757754 std::shared_ptr<TimingReport> timing_report,
758755 std::shared_ptr<ClockTreeReport> clock_report,
759756 utl::Logger* logger,
760- WebViewerHook* viewer_hook);
757+ WebViewerHook* viewer_hook,
758+ int max_in_flight);
761759
762760 void run ();
763761
@@ -771,14 +769,16 @@ DetectSession::DetectSession(Tcp::socket&& socket,
771769 std::shared_ptr<TimingReport> timing_report,
772770 std::shared_ptr<ClockTreeReport> clock_report,
773771 utl::Logger* logger,
774- WebViewerHook* viewer_hook)
772+ WebViewerHook* viewer_hook,
773+ int max_in_flight)
775774 : stream_(std::move(socket)),
776775 generator_ (std::move(generator)),
777776 tcl_eval_(std::move(tcl_eval)),
778777 timing_report_(std::move(timing_report)),
779778 clock_report_(std::move(clock_report)),
780779 logger_(logger),
781- viewer_hook_(viewer_hook)
780+ viewer_hook_(viewer_hook),
781+ max_in_flight_(max_in_flight)
782782{
783783}
784784
@@ -810,7 +810,8 @@ void DetectSession::on_read(beast::error_code ec)
810810 timing_report_,
811811 clock_report_,
812812 logger_,
813- viewer_hook_);
813+ viewer_hook_,
814+ max_in_flight_);
814815 websocket_session->run (std::move (req_));
815816 } else {
816817 // Regular HTTP - hand off to session with already-read request
@@ -833,6 +834,7 @@ class Listener : public std::enable_shared_from_this<Listener>
833834 std::shared_ptr<ClockTreeReport> clock_report_;
834835 utl::Logger* logger_;
835836 WebViewerHook* viewer_hook_ = nullptr ;
837+ int max_in_flight_ = 16 ;
836838
837839 public:
838840 Listener (net::io_context& ioc,
@@ -842,7 +844,8 @@ class Listener : public std::enable_shared_from_this<Listener>
842844 std::shared_ptr<TimingReport> timing_report,
843845 std::shared_ptr<ClockTreeReport> clock_report,
844846 utl::Logger* logger,
845- WebViewerHook* viewer_hook);
847+ WebViewerHook* viewer_hook,
848+ int max_in_flight);
846849
847850 void run () { do_accept (); }
848851
@@ -870,15 +873,17 @@ Listener::Listener(net::io_context& ioc,
870873 std::shared_ptr<TimingReport> timing_report,
871874 std::shared_ptr<ClockTreeReport> clock_report,
872875 utl::Logger* logger,
873- WebViewerHook* viewer_hook)
876+ WebViewerHook* viewer_hook,
877+ int max_in_flight)
874878 : ioc_(ioc),
875879 acceptor_(ioc),
876880 generator_(std::move(generator)),
877881 tcl_eval_(std::move(tcl_eval)),
878882 timing_report_(std::move(timing_report)),
879883 clock_report_(std::move(clock_report)),
880884 logger_(logger),
881- viewer_hook_(viewer_hook)
885+ viewer_hook_(viewer_hook),
886+ max_in_flight_(max_in_flight)
882887{
883888 beast::error_code ec;
884889
@@ -929,7 +934,8 @@ void Listener::on_accept(beast::error_code ec, Tcp::socket socket)
929934 timing_report_,
930935 clock_report_,
931936 logger_,
932- viewer_hook_)
937+ viewer_hook_,
938+ max_in_flight_)
933939 ->run ();
934940 }
935941 do_accept ();
@@ -1317,7 +1323,8 @@ ListenerHandle createAndRunListener(
13171323 std::shared_ptr<TimingReport> timing_report,
13181324 std::shared_ptr<ClockTreeReport> clock_report,
13191325 utl::Logger* logger,
1320- WebViewerHook* viewer_hook)
1326+ WebViewerHook* viewer_hook,
1327+ int max_in_flight)
13211328{
13221329 auto listener = std::make_shared<Listener>(ioc,
13231330 endpoint,
@@ -1326,7 +1333,8 @@ ListenerHandle createAndRunListener(
13261333 std::move (timing_report),
13271334 std::move (clock_report),
13281335 logger,
1329- viewer_hook);
1336+ viewer_hook,
1337+ max_in_flight);
13301338 listener->run ();
13311339 return {.shutdown = [listener]() { listener->close (); },
13321340 .port = listener->port ()};
0 commit comments