Just use stack allocations in parsing by default.

This commit is contained in:
Chris Marsh 2017-07-24 14:59:45 -07:00
parent 63058ddf23
commit 38c0599380
4 changed files with 59 additions and 30 deletions

View file

@ -82,35 +82,56 @@ extern "C" void Discord_UpdateConnection()
} }
else { else {
// reads // reads
JsonDocument message;
while (Connection->Read(message)) { // json parser will use this buffer first, then allocate more if needed; I seriously doubt we send any messages that would use all of this, though.
char parseBuffer[32 * 1024];
for (;;) {
PoolAllocator pa(parseBuffer, sizeof(parseBuffer));
StackAllocator sa;
JsonDocument message(rapidjson::kObjectType, &pa, sizeof(sa.fixedBuffer_), &sa);
if (!Connection->Read(message)) {
break;
}
const char* evtName = nullptr;
auto evt = message.FindMember("evt");
if (evt != message.MemberEnd() && evt->value.IsString()) {
evtName = evt->value.GetString();
}
auto nonce = message.FindMember("nonce"); auto nonce = message.FindMember("nonce");
if (nonce != message.MemberEnd() && nonce->value.IsString()) { if (nonce != message.MemberEnd() && nonce->value.IsString()) {
// in responses only -- should use to match up response when needed. // in responses only -- should use to match up response when needed.
//auto cmd = message.FindMember("cmd"); needed?
if (evtName && strcmp(evtName, "ERROR") == 0) {
auto data = message.FindMember("data");
LastErrorCode = data->value["code"].GetInt();
StringCopy(LastErrorMessage, data->value["message"].GetString());
GotErrorMessage.store(true);
}
} }
else { else {
// should have evt == name of event, optional data // should have evt == name of event, optional data
auto evt = message.FindMember("evt"); if (evtName == nullptr) {
if (evt != message.MemberEnd() && evt->value.IsString()) { continue;
const char* evtName = evt->value.GetString(); }
// todo ug // todo ug
if (strcmp(evtName, "PRESENCE_REQUESTED") == 0) { if (strcmp(evtName, "PRESENCE_REQUESTED") == 0) {
WasPresenceRequested.store(true); WasPresenceRequested.store(true);
} }
else if (strcmp(evtName, "JOIN_GAME") == 0) { else if (strcmp(evtName, "JOIN_GAME") == 0) {
auto data = message.FindMember("data"); auto data = message.FindMember("data");
auto secret = data->value["secret"].GetString(); auto secret = data->value["secret"].GetString();
StringCopy(JoinGameSecret, secret); StringCopy(JoinGameSecret, secret);
WasJoinGame.store(true); WasJoinGame.store(true);
} }
else if (strcmp(evtName, "SPECTATE_GAME") == 0) { else if (strcmp(evtName, "SPECTATE_GAME") == 0) {
auto data = message.FindMember("data"); auto data = message.FindMember("data");
auto secret = data->value["secret"].GetString(); auto secret = data->value["secret"].GetString();
StringCopy(SpectateGameSecret, secret); StringCopy(SpectateGameSecret, secret);
WasSpectateGame.store(true); WasSpectateGame.store(true);
}
} }
} }
} }

View file

@ -34,7 +34,10 @@ void RpcConnection::Open()
} }
if (state == State::SentHandshake) { if (state == State::SentHandshake) {
JsonDocument message; char parseBuffer[32 * 1024];
PoolAllocator pa(parseBuffer, sizeof(parseBuffer));
StackAllocator sa;
JsonDocument message(rapidjson::kObjectType, &pa, sizeof(sa.fixedBuffer_), &sa);
if (Read(message)) { if (Read(message)) {
auto cmd = message.FindMember("cmd"); auto cmd = message.FindMember("cmd");
if (cmd == message.MemberEnd() || !cmd->value.IsString()) { if (cmd == message.MemberEnd() || !cmd->value.IsString()) {

View file

@ -2,6 +2,8 @@
#include "connection.h" #include "connection.h"
#include "discord-rpc.h" #include "discord-rpc.h"
MallocAllocator MallocAllocatorInst;
// it's ever so slightly faster to not have to strlen the key // it's ever so slightly faster to not have to strlen the key
template<typename T> template<typename T>
void WriteKey(JsonWriter& w, T& k) { void WriteKey(JsonWriter& w, T& k) {
@ -46,7 +48,7 @@ void JsonWriteCommandEnd(JsonWriter& writer)
size_t JsonWriteRichPresenceObj(char* dest, size_t maxLen, int nonce, int pid, const DiscordRichPresence* presence) size_t JsonWriteRichPresenceObj(char* dest, size_t maxLen, int nonce, int pid, const DiscordRichPresence* presence)
{ {
DirectStringBuffer sb(dest, maxLen); DirectStringBuffer sb(dest, maxLen);
WriterAllocator wa; StackAllocator wa;
JsonWriter writer(sb, &wa, WriterNestingLevels); JsonWriter writer(sb, &wa, WriterNestingLevels);
JsonWriteCommandStart(writer, nonce, "SET_ACTIVITY"); JsonWriteCommandStart(writer, nonce, "SET_ACTIVITY");
@ -132,7 +134,7 @@ size_t JsonWriteRichPresenceObj(char* dest, size_t maxLen, int nonce, int pid, c
size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId) size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char* applicationId)
{ {
DirectStringBuffer sb(dest, maxLen); DirectStringBuffer sb(dest, maxLen);
WriterAllocator wa; StackAllocator wa;
JsonWriter writer(sb, &wa, WriterNestingLevels); JsonWriter writer(sb, &wa, WriterNestingLevels);
writer.StartObject(); writer.StartObject();
@ -148,7 +150,7 @@ size_t JsonWriteHandshakeObj(char* dest, size_t maxLen, int version, const char*
size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName) size_t JsonWriteSubscribeCommand(char* dest, size_t maxLen, int nonce, const char* evtName)
{ {
DirectStringBuffer sb(dest, maxLen); DirectStringBuffer sb(dest, maxLen);
WriterAllocator wa; StackAllocator wa;
JsonWriter writer(sb, &wa, WriterNestingLevels); JsonWriter writer(sb, &wa, WriterNestingLevels);
writer.StartObject(); writer.StartObject();

View file

@ -63,7 +63,7 @@ public:
static void Free(void* ptr) { /* shrug */ } static void Free(void* ptr) { /* shrug */ }
}; };
template<int Size> template<size_t Size>
class FixedLinearAllocator : public LinearAllocator { class FixedLinearAllocator : public LinearAllocator {
public: public:
char fixedBuffer_[Size]; char fixedBuffer_[Size];
@ -98,9 +98,12 @@ public:
} }
}; };
using MallocAllocator = rapidjson::CrtAllocator;
extern MallocAllocator MallocAllocatorInst;
using PoolAllocator = rapidjson::MemoryPoolAllocator<MallocAllocator>;
using UTF8 = rapidjson::UTF8<char>; using UTF8 = rapidjson::UTF8<char>;
// Writer appears to need about 16 bytes per nested object level (with 64bit size_t) // Writer appears to need about 16 bytes per nested object level (with 64bit size_t)
using WriterAllocator = FixedLinearAllocator<2048>; using StackAllocator = FixedLinearAllocator<2048>;
constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t)); constexpr size_t WriterNestingLevels = 2048 / (2 * sizeof(size_t));
using JsonWriter = rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, WriterAllocator, rapidjson::kWriteNoFlags>; using JsonWriter = rapidjson::Writer<DirectStringBuffer, UTF8, UTF8, StackAllocator, rapidjson::kWriteNoFlags>;
using JsonDocument = rapidjson::GenericDocument<UTF8>; using JsonDocument = rapidjson::GenericDocument<UTF8, PoolAllocator, FixedLinearAllocator<2048>>;