Bug 1168265 - Clean up ChunkedJSONWriteFunc. (r=mstange)

This commit is contained in:
Shu-yu Guo 2015-05-26 22:58:40 -07:00
parent 35c01fcb4f
commit 623cc01e46
2 changed files with 90 additions and 57 deletions

View File

@ -7,6 +7,65 @@
#include "ProfileJSONWriter.h"
void
ChunkedJSONWriteFunc::Write(const char* aStr)
{
MOZ_ASSERT(mChunkPtr >= mChunkList.back().get() && mChunkPtr <= mChunkEnd);
MOZ_ASSERT(mChunkEnd >= mChunkList.back().get() + mChunkLengths.back());
size_t len = strlen(aStr);
// Most strings to be written are small, but subprocess profiles (e.g.,
// from the content process in e10s) may be huge. If the string is larger
// than a chunk, allocate its own chunk.
char* newPtr;
if (len >= kChunkSize) {
AllocChunk(len);
newPtr = mChunkPtr + len;
} else {
newPtr = mChunkPtr + len;
if (newPtr > mChunkEnd) {
AllocChunk(kChunkSize);
newPtr = mChunkPtr + len;
}
}
memcpy(mChunkPtr, aStr, len);
mChunkPtr = newPtr;
mChunkLengths.back() += len;
}
mozilla::UniquePtr<char[]>
ChunkedJSONWriteFunc::CopyData() const
{
MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
size_t totalLen = 1;
for (size_t i = 0; i < mChunkLengths.length(); i++) {
MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]);
totalLen += mChunkLengths[i];
}
mozilla::UniquePtr<char[]> c = mozilla::MakeUnique<char[]>(totalLen);
char* ptr = c.get();
for (size_t i = 0; i < mChunkList.length(); i++) {
size_t len = mChunkLengths[i];
memcpy(ptr, mChunkList[i].get(), len);
ptr += len;
}
*ptr = '\0';
return c;
}
void
ChunkedJSONWriteFunc::AllocChunk(size_t aChunkSize)
{
MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
mozilla::UniquePtr<char[]> newChunk = mozilla::MakeUnique<char[]>(aChunkSize);
mChunkPtr = newChunk.get();
mChunkEnd = mChunkPtr + aChunkSize;
MOZ_ALWAYS_TRUE(mChunkLengths.append(0));
MOZ_ALWAYS_TRUE(mChunkList.append(mozilla::Move(newChunk)));
}
void
SpliceableJSONWriter::Splice(const ChunkedJSONWriteFunc* aFunc)
{

View File

@ -15,78 +15,50 @@
class SpliceableChunkedJSONWriter;
// On average, profile JSONs are large enough such that we want to avoid
// reallocating its buffer when expanding. Additionally, the contents of the
// profile are not accessed until the profile is entirely written. For these
// reasons we use a chunked writer that keeps an array of chunks, which is
// concatenated together after writing is finished.
class ChunkedJSONWriteFunc : public mozilla::JSONWriteFunc
{
public:
friend class SpliceableJSONWriter;
const static size_t kChunkSize = 4096 * 512;
char* mChunkPtr;
char* mChunkEnd;
mozilla::Vector<mozilla::UniquePtr<char[]>> mChunkList;
mozilla::Vector<size_t> mChunkLengths;
void AllocChunk(size_t aChunkSize) {
MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
mozilla::UniquePtr<char[]> newChunk = mozilla::MakeUnique<char[]>(aChunkSize);
mChunkPtr = newChunk.get();
mChunkEnd = mChunkPtr + aChunkSize;
MOZ_ALWAYS_TRUE(mChunkLengths.append(0));
MOZ_ALWAYS_TRUE(mChunkList.append(mozilla::Move(newChunk)));
}
public:
ChunkedJSONWriteFunc() {
AllocChunk(kChunkSize);
}
void Write(const char* aStr) override {
size_t len = strlen(aStr);
void Write(const char* aStr) override;
mozilla::UniquePtr<char[]> CopyData() const;
// Most strings to be written are small, but subprocess profiles (e.g.,
// from the content process in e10s) may be huge. If the string is larger
// than a chunk, allocate its own chunk.
char* newPtr;
if (len >= kChunkSize) {
AllocChunk(len + 1);
newPtr = mChunkPtr + len;
} else {
newPtr = mChunkPtr + len;
if (newPtr >= mChunkEnd) {
MOZ_ASSERT(*mChunkPtr == '\0');
AllocChunk(kChunkSize);
newPtr = mChunkPtr + len;
}
}
private:
void AllocChunk(size_t aChunkSize);
memcpy(mChunkPtr, aStr, len);
mChunkPtr = newPtr;
mChunkLengths.back() += len;
*mChunkPtr = '\0';
}
static const size_t kChunkSize = 4096 * 512;
mozilla::UniquePtr<char[]> CopyData() {
MOZ_ASSERT(mChunkLengths.length() == mChunkList.length());
size_t totalLen = 1;
for (size_t i = 0; i < mChunkLengths.length(); i++) {
MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]);
totalLen += mChunkLengths[i];
}
mozilla::UniquePtr<char[]> c = mozilla::MakeUnique<char[]>(totalLen);
char* ptr = c.get();
for (size_t i = 0; i < mChunkList.length(); i++) {
size_t len = mChunkLengths[i];
memcpy(ptr, mChunkList[i].get(), len);
ptr += len;
}
*ptr = '\0';
return c;
}
// Pointer for writing inside the current chunk.
//
// The current chunk is always at the back of mChunkList, i.e.,
// mChunkList.back() <= mChunkPtr <= mChunkEnd.
char* mChunkPtr;
// Pointer to the end of the current chunk.
//
// The current chunk is always at the back of mChunkList, i.e.,
// mChunkEnd >= mChunkList.back() + mChunkLengths.back().
char* mChunkEnd;
// List of chunks and their lengths.
//
// For all i, the length of the string in mChunkList[i] is
// mChunkLengths[i].
mozilla::Vector<mozilla::UniquePtr<char[]>> mChunkList;
mozilla::Vector<size_t> mChunkLengths;
};
struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc
{
std::ostream& mStream;
explicit OStreamJSONWriteFunc(std::ostream& aStream)
: mStream(aStream)
{ }
@ -94,6 +66,8 @@ struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc
void Write(const char* aStr) override {
mStream << aStr;
}
std::ostream& mStream;
};
class SpliceableJSONWriter : public mozilla::JSONWriter