fix: json_spirit::write_string is very CPU intensive, especially for large JSON documents. The cluster controller would call this function for each status reply it needed to send, resulting in a slow task.

This commit is contained in:
Evan Tschannen 2018-08-15 19:39:06 -07:00
parent b7e08377b4
commit e770629229
3 changed files with 11 additions and 4 deletions

View File

@ -188,13 +188,19 @@ struct StatusRequest {
struct StatusReply {
StatusObject statusObj;
std::string statusStr;
StatusReply() {}
StatusReply( StatusObject statusObj ) : statusObj(statusObj) {}
explicit StatusReply(StatusObject obj) : statusObj(obj), statusStr(json_spirit::write_string(json_spirit::mValue(obj))) {}
template <class Ar>
void serialize(Ar& ar) {
ar & statusObj;
ar & statusStr;
if( ar.isDeserializing ) {
json_spirit::mValue mv;
json_spirit::read_string( statusStr, mv );
statusObj = StatusObject(mv.get_obj());
}
}
};

View File

@ -1807,7 +1807,7 @@ ACTOR Future<Void> statusServer(FutureStream< StatusRequest> requests,
}
}
ErrorOr<StatusReply> result = wait(errorOr(clusterGetStatus(self->db.serverInfo, self->cx, workers, self->db.workersWithIssues, self->db.clientsWithIssues, self->db.clientVersionMap, self->db.traceLogGroupMap, coordinators, incompatibleConnections, self->datacenterVersionDifference)));
state ErrorOr<StatusReply> result = wait(errorOr(clusterGetStatus(self->db.serverInfo, self->cx, workers, self->db.workersWithIssues, self->db.clientsWithIssues, self->db.clientVersionMap, self->db.traceLogGroupMap, coordinators, incompatibleConnections, self->datacenterVersionDifference)));
if (result.isError() && result.getError().code() == error_code_actor_cancelled)
throw result.getError();
@ -1821,6 +1821,7 @@ ACTOR Future<Void> statusServer(FutureStream< StatusRequest> requests,
else
requests_batch.back().reply.send(result.get());
requests_batch.pop_back();
Void _ = wait( yield() );
}
}
catch (Error &e) {

View File

@ -1922,7 +1922,7 @@ ACTOR Future<StatusReply> clusterGetStatus(
statusObj["cluster_controller_timestamp"] = clusterTime;
}
return statusObj;
return StatusReply(statusObj);
} catch( Error&e ) {
TraceEvent(SevError, "StatusError").error(e);
throw;