diff --git a/Core/Debugger/WebSocket/DisasmSubscriber.cpp b/Core/Debugger/WebSocket/DisasmSubscriber.cpp index 25e15bec2f..f3507aa34a 100644 --- a/Core/Debugger/WebSocket/DisasmSubscriber.cpp +++ b/Core/Debugger/WebSocket/DisasmSubscriber.cpp @@ -290,6 +290,10 @@ void WebSocketDisasmState::Disasm(DebuggerRequest &req) { disasm_.getLine(addr, displaySymbols, line); WriteDisasmLine(json, line); addr += line.totalSize; + + // These are pretty long, so let's grease the wheels a bit. + if (i % 50 == 0) + req.Flush(); } json.pop(); diff --git a/Core/Debugger/WebSocket/WebSocketUtils.cpp b/Core/Debugger/WebSocket/WebSocketUtils.cpp index d21b93e9d3..fe6e343b0a 100644 --- a/Core/Debugger/WebSocket/WebSocketUtils.cpp +++ b/Core/Debugger/WebSocket/WebSocketUtils.cpp @@ -32,12 +32,21 @@ JsonWriter &DebuggerRequest::Respond() { void DebuggerRequest::Finish() { if (responseBegun_ && !responseSent_) { writer_.end(); - ws->Send(writer_.str()); + if (responsePartial_) + ws->AddFragment(true, writer_.str()); + else + ws->Send(writer_.str()); responseBegun_ = false; responseSent_ = true; + responsePartial_ = false; } } +void DebuggerRequest::Flush() { + ws->AddFragment(false, writer_.flush()); + responsePartial_ = true; +} + static bool U32FromString(const char *str, uint32_t *out, bool allowFloat) { if (TryParse(str, out)) return true; diff --git a/Core/Debugger/WebSocket/WebSocketUtils.h b/Core/Debugger/WebSocket/WebSocketUtils.h index 1391e6614c..6bad56e5b9 100644 --- a/Core/Debugger/WebSocket/WebSocketUtils.h +++ b/Core/Debugger/WebSocket/WebSocketUtils.h @@ -85,12 +85,14 @@ struct DebuggerRequest { bool ParamString(const char *name, std::string *out, DebuggerParamType type = DebuggerParamType::REQUIRED); JsonWriter &Respond(); + void Flush(); void Finish(); private: JsonWriter writer_; bool responseBegun_ = false; bool responseSent_ = false; + bool responsePartial_ = false; }; typedef std::function DebuggerEventHandler; diff --git a/ext/native/json/json_writer.cpp b/ext/native/json/json_writer.cpp index 3cc625e13d..15defaac84 100644 --- a/ext/native/json/json_writer.cpp +++ b/ext/native/json/json_writer.cpp @@ -72,7 +72,7 @@ const char *JsonWriter::comma() const { const char *JsonWriter::arrayComma() const { if (stack_.back().first) { - return "\n"; + return pretty_ ? "\n" : ""; } else { return pretty_ ? ", " : ","; } @@ -159,7 +159,7 @@ void JsonWriter::writeString(const char *value) { void JsonWriter::writeString(const char *name, const char *value) { str_ << comma() << indent() << "\""; writeEscapedString(name); - str_ << "\": \""; + str_ << (pretty_ ? "\": \"" : "\":\""); writeEscapedString(value); str_ << "\""; stack_.back().first = false; diff --git a/ext/native/json/json_writer.h b/ext/native/json/json_writer.h index 06afb66bc7..ee63708fb4 100644 --- a/ext/native/json/json_writer.h +++ b/ext/native/json/json_writer.h @@ -59,6 +59,12 @@ public: return str_.str(); } + std::string flush() { + std::string result = str_.str(); + str_.str(""); + return result; + } + enum { NORMAL = 0, PRETTY = 1, diff --git a/ext/native/net/websocket_server.cpp b/ext/native/net/websocket_server.cpp index 0302ddbb22..40cadfb733 100644 --- a/ext/native/net/websocket_server.cpp +++ b/ext/native/net/websocket_server.cpp @@ -46,6 +46,8 @@ enum class Opcode { CONTROL_MAX = 10, }; +static const size_t OUT_PRESSURE = 65536; + static inline std::string TrimString(const std::string &s) { auto wsfront = std::find_if_not(s.begin(), s.end(), [](int c) { // isspace() expects 0 - 255, so convert any sign-extended value. @@ -508,6 +510,14 @@ void WebSocketServer::SendBytes(const void *p, size_t sz) { size_t pos = outBuf_.size(); outBuf_.resize(pos + sz); memcpy(&outBuf_[pos], data, sz); + + if (pos + sz > lastPressure_ + OUT_PRESSURE) { + size_t pushed = out_->PushAtMost((const char *)&outBuf_[0], outBuf_.size()); + if (pushed != 0) { + outBuf_.erase(outBuf_.begin(), outBuf_.begin() + pushed); + } + lastPressure_ = outBuf_.size(); + } } } @@ -529,6 +539,7 @@ void WebSocketServer::SendFlush() { // Hopefully this is usually the entire buffer. outBuf_.erase(outBuf_.begin(), outBuf_.begin() + totalPushed); } + lastPressure_ = outBuf_.size(); } }; diff --git a/ext/native/net/websocket_server.h b/ext/native/net/websocket_server.h index 98426f53cf..2c4c59739e 100644 --- a/ext/native/net/websocket_server.h +++ b/ext/native/net/websocket_server.h @@ -86,6 +86,7 @@ protected: OutputSink *out_ = nullptr; WebSocketClose closeReason_ = WebSocketClose::NO_STATUS; std::vector outBuf_; + size_t lastPressure_ = 0; std::vector pendingBuf_; uint8_t pendingMask_[4]{};