aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bench/WriterBench.cpp40
-rw-r--r--gyp/bench.gypi1
-rw-r--r--src/core/SkWriter32.cpp28
-rw-r--r--tests/Writer32Test.cpp55
4 files changed, 111 insertions, 13 deletions
diff --git a/bench/WriterBench.cpp b/bench/WriterBench.cpp
new file mode 100644
index 0000000000..2de653c374
--- /dev/null
+++ b/bench/WriterBench.cpp
@@ -0,0 +1,40 @@
+
+/*
+ * Copyright 2012 The Android Open Source Project
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkBenchmark.h"
+#include "SkCanvas.h"
+#include "SkWriter32.h"
+
+class WriterBench : public SkBenchmark {
+public:
+ WriterBench(void* param) : INHERITED(param) {}
+
+protected:
+ virtual const char* onGetName() SK_OVERRIDE {
+ return "writer";
+ }
+
+ virtual void onDraw(SkCanvas* canvas) SK_OVERRIDE {
+ static const char gStr[] = "abcdefghimjklmnopqrstuvwxyz";
+ static const size_t gLen = strlen(gStr);
+ SkWriter32 writer(256 * 4);
+ for (int i = 0; i < SkBENCHLOOP(800); i++) {
+ for (size_t j = 0; j <= gLen; j++) {
+ writer.writeString(gStr, j);
+ }
+ }
+ }
+
+private:
+ typedef SkBenchmark INHERITED;
+};
+
+////////////////////////////////////////////////////////////////////////////////
+
+static SkBenchmark* fact(void* p) { return new WriterBench(p); }
+static BenchRegistry gReg(fact);
diff --git a/gyp/bench.gypi b/gyp/bench.gypi
index f809b6431e..e32db41117 100644
--- a/gyp/bench.gypi
+++ b/gyp/bench.gypi
@@ -34,6 +34,7 @@
'../bench/ShaderMaskBench.cpp',
'../bench/TextBench.cpp',
'../bench/VertBench.cpp',
+ '../bench/WriterBench.cpp',
],
}
diff --git a/src/core/SkWriter32.cpp b/src/core/SkWriter32.cpp
index 23f51b93fe..926a4303ec 100644
--- a/src/core/SkWriter32.cpp
+++ b/src/core/SkWriter32.cpp
@@ -180,13 +180,15 @@ void SkWriter32::flatten(void* dst) const {
}
void SkWriter32::writePad(const void* src, size_t size) {
- size_t alignedSize = SkAlign4(size);
- char* dst = (char*)this->reserve(alignedSize);
- memcpy(dst, src, size);
- dst += size;
- int n = alignedSize - size;
- while (--n >= 0) {
- *dst++ = 0;
+ if (size > 0) {
+ size_t alignedSize = SkAlign4(size);
+ char* dst = (char*)this->reserve(alignedSize);
+ // Pad the last four bytes with zeroes in one step. Some (or all) will
+ // be overwritten by the memcpy.
+ uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4));
+ *padding = 0;
+ // Copy the actual data.
+ memcpy(dst, src, size);
}
}
@@ -279,13 +281,13 @@ void SkWriter32::writeString(const char str[], size_t len) {
// add 1 since we also write a terminating 0
size_t alignedLen = SkAlign4(len + 1);
char* ptr = (char*)this->reserve(alignedLen);
- memcpy(ptr, str, len);
- // Add the terminating 0, and pad the rest with 0s
- ptr += len;
- int n = alignedLen - len;
- while (--n >= 0) {
- *ptr++ = 0;
+ {
+ // Write the terminating 0 and fill in the rest with zeroes
+ uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4));
+ *padding = 0;
}
+ // Copy the string itself.
+ memcpy(ptr, str, len);
}
size_t SkWriter32::WriteStringSize(const char* str, size_t len) {
diff --git a/tests/Writer32Test.cpp b/tests/Writer32Test.cpp
index 5c9d7ea58c..8b048a7b73 100644
--- a/tests/Writer32Test.cpp
+++ b/tests/Writer32Test.cpp
@@ -8,6 +8,7 @@
+#include "SkRandom.h"
#include "SkReader32.h"
#include "SkWriter32.h"
#include "Test.h"
@@ -86,6 +87,48 @@ static void test2(skiatest::Reporter* reporter, SkWriter32* writer) {
REPORTER_ASSERT(reporter, reader.eof());
}
+static void testWritePad(skiatest::Reporter* reporter, SkWriter32* writer) {
+ // Create some random data to write.
+ const size_t dataSize = 10<<2;
+ SkASSERT(SkIsAlign4(dataSize));
+
+ SkAutoMalloc originalData(dataSize);
+ {
+ SkRandom rand(0);
+ uint32_t* ptr = static_cast<uint32_t*>(originalData.get());
+ uint32_t* stop = ptr + (dataSize>>2);
+ while (ptr < stop) {
+ *ptr++ = rand.nextU();
+ }
+
+ // Write the random data to the writer at different lengths for
+ // different alignments.
+ for (size_t len = 0; len < dataSize; len++) {
+ writer->writePad(originalData.get(), len);
+ }
+ }
+
+ uint32_t totalBytes = writer->size();
+
+ SkAutoMalloc readStorage(totalBytes);
+ writer->flatten(readStorage.get());
+
+ SkReader32 reader;
+ reader.setMemory(readStorage.get(), totalBytes);
+
+ for (size_t len = 0; len < dataSize; len++) {
+ const char* readPtr = static_cast<const char*>(reader.skip(len));
+ // Ensure that the data read is the same as what was written.
+ REPORTER_ASSERT(reporter, memcmp(readPtr, originalData.get(), len) == 0);
+ // Ensure that the rest is padded with zeroes.
+ const char* stop = readPtr + SkAlign4(len);
+ readPtr += len;
+ while (readPtr < stop) {
+ REPORTER_ASSERT(reporter, *readPtr++ == 0);
+ }
+ }
+}
+
static void Tests(skiatest::Reporter* reporter) {
// dynamic allocator
{
@@ -95,6 +138,9 @@ static void Tests(skiatest::Reporter* reporter) {
writer.reset();
test2(reporter, &writer);
+
+ writer.reset();
+ testWritePad(reporter, &writer);
}
// single-block
@@ -108,6 +154,9 @@ static void Tests(skiatest::Reporter* reporter) {
writer.reset(storage, sizeof(storage));
test2(reporter, &writer);
+
+ writer.reset(storage, sizeof(storage));
+ testWritePad(reporter, &writer);
}
// small storage
@@ -116,6 +165,9 @@ static void Tests(skiatest::Reporter* reporter) {
test1(reporter, &writer);
writer.reset(); // should just rewind our storage
test2(reporter, &writer);
+
+ writer.reset();
+ testWritePad(reporter, &writer);
}
// large storage
@@ -124,6 +176,9 @@ static void Tests(skiatest::Reporter* reporter) {
test1(reporter, &writer);
writer.reset(); // should just rewind our storage
test2(reporter, &writer);
+
+ writer.reset();
+ testWritePad(reporter, &writer);
}
test_ptr(reporter);