зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1168265 - Clean up ChunkedJSONWriteFunc. (r=mstange)
This commit is contained in:
Родитель
9f94c8fcbf
Коммит
3e9695abda
|
@ -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
|
||||||
|
|
Загрузка…
Ссылка в новой задаче