Permalink
Browse files

Debugger: Use fragments for long chunks.

Gets it on the wire faster.  More importantly, this allows us to usually
avoid rampant memory allocation even for large responses.
  • Loading branch information...
unknownbrackets committed May 1, 2018
1 parent e746a2d commit ccea863f00dbcf44ca6c4191a0af39694a0e48f2
@@ -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();
@@ -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;
@@ -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<void(DebuggerRequest &req)> DebuggerEventHandler;
@@ -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;
@@ -59,6 +59,12 @@ class JsonWriter {
return str_.str();
}
std::string flush() {
std::string result = str_.str();
str_.str("");
return result;
}
enum {
NORMAL = 0,
PRETTY = 1,
@@ -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();
}
};
@@ -86,6 +86,7 @@ class WebSocketServer {
OutputSink *out_ = nullptr;
WebSocketClose closeReason_ = WebSocketClose::NO_STATUS;
std::vector<uint8_t> outBuf_;
size_t lastPressure_ = 0;
std::vector<uint8_t> pendingBuf_;
uint8_t pendingMask_[4]{};

0 comments on commit ccea863

Please sign in to comment.