SkDynamicMemoryWStream::detachAsData more memory efficent
I did some testing with very large datasets, and the difference in max
RSS is measurable and significant.
Change-Id: I6bb2f795d5b4f6ebdba42c3089dc85a278355d48
Reviewed-on: https://skia-review.googlesource.com/9686
Commit-Queue: Hal Canary <halcanary@google.com>
Reviewed-by: Ben Wagner <bungeman@google.com>
diff --git a/include/core/SkStream.h b/include/core/SkStream.h
index 10929a8..8df59af 100644
--- a/include/core/SkStream.h
+++ b/include/core/SkStream.h
@@ -376,6 +376,9 @@
void copyTo(void* dst) const;
void writeToStream(SkWStream* dst) const;
+ /** Equivalent to copyTo() followed by reset(), but may save memory use. */
+ void copyToAndReset(void* dst);
+
/** Return the contents as SkData, and then reset the stream. */
sk_sp<SkData> detachAsData();
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index 1435dab..133df83 100644
--- a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -570,15 +570,31 @@
}
}
+
+void SkDynamicMemoryWStream::copyToAndReset(void* ptr) {
+ // By looping through the source and freeing as we copy, we
+ // can reduce real memory use with large streams.
+ char* dst = reinterpret_cast<char*>(ptr);
+ Block* block = fHead;
+ while (block != nullptr) {
+ size_t len = block->written();
+ memcpy(dst, block->start(), len);
+ dst += len;
+ Block* next = block->fNext;
+ sk_free(block);
+ block = next;
+ }
+ fHead = fTail = nullptr;
+ fBytesWrittenBeforeTail = 0;
+}
+
sk_sp<SkData> SkDynamicMemoryWStream::detachAsData() {
const size_t size = this->bytesWritten();
if (0 == size) {
return SkData::MakeEmpty();
}
-
sk_sp<SkData> data = SkData::MakeUninitialized(size);
- this->copyTo(data->writable_data());
- this->reset(); // this is the "detach" part
+ this->copyToAndReset(data->writable_data());
return data;
}
diff --git a/tests/StreamTest.cpp b/tests/StreamTest.cpp
index 2e476a1..8b5b2ae 100644
--- a/tests/StreamTest.cpp
+++ b/tests/StreamTest.cpp
@@ -410,6 +410,26 @@
}
}
+DEF_TEST(DynamicMemoryWStream_detachAsData, r) {
+ const char az[] = "abcdefghijklmnopqrstuvwxyz";
+ const unsigned N = 40000;
+ SkDynamicMemoryWStream dmws;
+ for (unsigned i = 0; i < N; ++i) {
+ dmws.writeText(az);
+ }
+ REPORTER_ASSERT(r, dmws.bytesWritten() == N * strlen(az));
+ auto data = dmws.detachAsData();
+ REPORTER_ASSERT(r, data->size() == N * strlen(az));
+ const uint8_t* ptr = data->bytes();
+ for (unsigned i = 0; i < N; ++i) {
+ if (0 != memcmp(ptr, az, strlen(az))) {
+ ERRORF(r, "detachAsData() memcmp failed");
+ return;
+ }
+ ptr += strlen(az);
+ }
+}
+
DEF_TEST(StreamCopy, reporter) {
SkRandom random(123456);
static const int N = 10000;