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

This commit is contained in:
Shu-yu Guo 2015-05-26 22:58:40 -07:00
Родитель 9f94c8fcbf
Коммит 3e9695abda
2 изменённых файлов: 90 добавлений и 57 удалений

Просмотреть файл

@ -7,6 +7,65 @@
#include "ProfileJSONWriter.h" #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 void
SpliceableJSONWriter::Splice(const ChunkedJSONWriteFunc* aFunc) SpliceableJSONWriter::Splice(const ChunkedJSONWriteFunc* aFunc)
{ {

Просмотреть файл

@ -15,78 +15,50 @@
class SpliceableChunkedJSONWriter; 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 class ChunkedJSONWriteFunc : public mozilla::JSONWriteFunc
{ {
public:
friend class SpliceableJSONWriter; 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() { ChunkedJSONWriteFunc() {
AllocChunk(kChunkSize); AllocChunk(kChunkSize);
} }
void Write(const char* aStr) override { void Write(const char* aStr) override;
size_t len = strlen(aStr); mozilla::UniquePtr<char[]> CopyData() const;
// Most strings to be written are small, but subprocess profiles (e.g., private:
// from the content process in e10s) may be huge. If the string is larger void AllocChunk(size_t aChunkSize);
// 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;
}
}
memcpy(mChunkPtr, aStr, len); static const size_t kChunkSize = 4096 * 512;
mChunkPtr = newPtr;
mChunkLengths.back() += len;
*mChunkPtr = '\0';
}
mozilla::UniquePtr<char[]> CopyData() { // Pointer for writing inside the current chunk.
MOZ_ASSERT(mChunkLengths.length() == mChunkList.length()); //
size_t totalLen = 1; // The current chunk is always at the back of mChunkList, i.e.,
for (size_t i = 0; i < mChunkLengths.length(); i++) { // mChunkList.back() <= mChunkPtr <= mChunkEnd.
MOZ_ASSERT(strlen(mChunkList[i].get()) == mChunkLengths[i]); char* mChunkPtr;
totalLen += mChunkLengths[i];
} // Pointer to the end of the current chunk.
mozilla::UniquePtr<char[]> c = mozilla::MakeUnique<char[]>(totalLen); //
char* ptr = c.get(); // The current chunk is always at the back of mChunkList, i.e.,
for (size_t i = 0; i < mChunkList.length(); i++) { // mChunkEnd >= mChunkList.back() + mChunkLengths.back().
size_t len = mChunkLengths[i]; char* mChunkEnd;
memcpy(ptr, mChunkList[i].get(), len);
ptr += len; // List of chunks and their lengths.
} //
*ptr = '\0'; // For all i, the length of the string in mChunkList[i] is
return c; // mChunkLengths[i].
} mozilla::Vector<mozilla::UniquePtr<char[]>> mChunkList;
mozilla::Vector<size_t> mChunkLengths;
}; };
struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc
{ {
std::ostream& mStream;
explicit OStreamJSONWriteFunc(std::ostream& aStream) explicit OStreamJSONWriteFunc(std::ostream& aStream)
: mStream(aStream) : mStream(aStream)
{ } { }
@ -94,6 +66,8 @@ struct OStreamJSONWriteFunc : public mozilla::JSONWriteFunc
void Write(const char* aStr) override { void Write(const char* aStr) override {
mStream << aStr; mStream << aStr;
} }
std::ostream& mStream;
}; };
class SpliceableJSONWriter : public mozilla::JSONWriter class SpliceableJSONWriter : public mozilla::JSONWriter