Chromium Code Reviews| Index: content/child/child_thread_impl_perftest.cc |
| diff --git a/content/child/child_thread_impl_perftest.cc b/content/child/child_thread_impl_perftest.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..0e565daa7247ba207014d779b7dffaefac87da2e |
| --- /dev/null |
| +++ b/content/child/child_thread_impl_perftest.cc |
| @@ -0,0 +1,185 @@ |
| +// Copyright 2015 The Chromium Authors. All rights reserved. |
|
reveman
2015/06/18 21:08:57
hm, this is a browser perf test. is _perftest.cc t
vignatti (out of this project)
2015/06/18 21:59:45
I don't know where to add this test to be honest.
reveman
2015/06/22 20:41:57
Does this need to be an integration test (browsert
|
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "base/bind.h" |
| +#include "base/command_line.h" |
| +#include "base/memory/scoped_vector.h" |
| +#include "base/time/time.h" |
| +#include "content/child/child_gpu_memory_buffer_manager.h" |
| +#include "content/child/child_thread_impl.h" |
| +#include "content/common/gpu/client/gpu_memory_buffer_impl.h" |
| +#include "content/public/common/content_switches.h" |
| +#include "content/public/test/content_browser_test.h" |
| +#include "content/public/test/content_browser_test_utils.h" |
| +#include "content/shell/browser/shell.h" |
| +#include "testing/perf/perf_test.h" |
| +#include "url/gurl.h" |
| + |
| +namespace content { |
| +namespace { |
| + |
| +static const int kNumRuns = 30; |
| + |
| +enum NativeBufferFlag { kDisableNativeBuffers, kEnableNativeBuffers }; |
| + |
| +enum MemoryOperation { kMemoryOperationWrite, kMemoryOperationNoop }; |
|
reveman
2015/06/18 21:08:57
would this make more sense as separate tests? Map,
vignatti (out of this project)
2015/06/18 21:59:46
Acknowledged.
|
| + |
| +class ChildThreadImplBrowserTest : public ContentBrowserTest { |
| + public: |
| + ChildThreadImplBrowserTest() |
| + : child_gpu_memory_buffer_manager_(nullptr) {} |
| + |
| + // Overridden from BrowserTestBase: |
| + void SetUpCommandLine(base::CommandLine* command_line) override { |
| + command_line->AppendSwitch(switches::kSingleProcess); |
| + } |
| + void SetUpOnMainThread() override { |
| + NavigateToURL(shell(), GURL(url::kAboutBlankURL)); |
| + PostTaskToInProcessRendererAndWait( |
| + base::Bind(&ChildThreadImplBrowserTest::SetUpOnChildThread, this)); |
| + } |
| + |
| + ChildGpuMemoryBufferManager* child_gpu_memory_buffer_manager() { |
| + return child_gpu_memory_buffer_manager_; |
| + } |
| + |
| + NativeBufferFlag native_buffer_flag_; |
|
reveman
2015/06/18 21:08:58
do we need this as a member?
vignatti (out of this project)
2015/06/18 21:59:46
Acknowledged.
|
| + |
| + private: |
| + void SetUpOnChildThread() { |
| + child_gpu_memory_buffer_manager_ = |
| + ChildThreadImpl::current()->gpu_memory_buffer_manager(); |
| + } |
| + |
| + ChildGpuMemoryBufferManager* child_gpu_memory_buffer_manager_; |
| +}; |
| + |
| +class ChildThreadImplGpuMemoryBufferPerfTest |
| + : public ChildThreadImplBrowserTest, |
| + public testing::WithParamInterface< |
| + ::testing::tuple<NativeBufferFlag, |
| + gfx::GpuMemoryBuffer::Format, |
| + MemoryOperation>> { |
| + public: |
| + // Overridden from BrowserTestBase: |
| + void SetUpCommandLine(base::CommandLine* command_line) override { |
| + ChildThreadImplBrowserTest::SetUpCommandLine(command_line); |
| + native_buffer_flag_ = ::testing::get<0>(GetParam()); |
| + switch (native_buffer_flag_) { |
| + case kEnableNativeBuffers: |
| + command_line->AppendSwitch(switches::kEnableNativeGpuMemoryBuffers); |
| + break; |
| + case kDisableNativeBuffers: |
| + break; |
| + } |
| + } |
| +}; |
| + |
| +std::string NativeBufferFlagName(NativeBufferFlag flag) { |
| + switch (flag) { |
| + case kDisableNativeBuffers: |
| + return "fallback"; |
|
reveman
2015/06/18 21:08:57
"fallback" can be confusing as kEnableNativeBuffer
vignatti (out of this project)
2015/06/18 21:59:46
Acknowledged.
|
| + case kEnableNativeBuffers: |
| + return "native"; |
| + } |
| + |
| + NOTREACHED(); |
| + return ""; |
| +} |
| + |
| +std::string MemoryOperationName(MemoryOperation operation) { |
| + switch (operation) { |
| + case kMemoryOperationWrite: |
| + return "write"; |
| + case kMemoryOperationNoop: |
| + return "noop"; |
| + } |
| + |
| + NOTREACHED(); |
| + return ""; |
| +} |
| + |
| +IN_PROC_BROWSER_TEST_P(ChildThreadImplGpuMemoryBufferPerfTest, |
| + Map) { |
| + gfx::GpuMemoryBuffer::Format format = ::testing::get<1>(GetParam()); |
| + gfx::Size buffer_size(4, 4); |
| + std::string flag_name = NativeBufferFlagName(native_buffer_flag_); |
| + MemoryOperation operation = ::testing::get<2>(GetParam()); |
| + std::string operation_name = MemoryOperationName(operation); |
| + |
| + scoped_ptr<gfx::GpuMemoryBuffer> buffer = |
| + child_gpu_memory_buffer_manager()->AllocateGpuMemoryBuffer( |
| + buffer_size, format, gfx::GpuMemoryBuffer::MAP); |
| + ASSERT_TRUE(buffer); |
| + EXPECT_EQ(format, buffer->GetFormat()); |
| + |
| + size_t num_planes = |
| + GpuMemoryBufferImpl::NumberOfPlanesForGpuMemoryBufferFormat(format); |
| + |
| + // Map buffer planes. |
| + scoped_ptr<void* []> planes(new void* [num_planes]); |
| + |
| + for (int i = 0; i < kNumRuns; ++i) { |
| + base::TimeTicks start = base::TimeTicks::Now(); |
| + bool rv = buffer->Map(planes.get()); |
| + base::TimeTicks end = base::TimeTicks::Now(); |
| + ASSERT_TRUE(rv); |
| + EXPECT_TRUE(buffer->IsMapped()); |
| + |
| + // TODO(vignatti): get the mean time and print to stdout only once. At the |
| + // moment it's being useful to check individual runs though cause for |
| + // example VGEM has way worse performance on its first runs (got check why). |
| + perf_test::PrintResult( |
| + "time_to_execute_map_", |
| + flag_name, |
| + operation_name, |
| + static_cast<size_t>((end - start).InMicroseconds()), |
| + "us", true); |
|
reveman
2015/06/18 21:08:57
can we just have one result per test? Map shows ti
vignatti (out of this project)
2015/06/18 21:59:46
as I said in the comment, I think right now I pref
|
| + |
| + // Get stride. |
| + scoped_ptr<int[]> strides(new int[num_planes]); |
| + buffer->GetStride(strides.get()); |
| + |
| + for (size_t plane = 0; plane < num_planes; ++plane) { |
| + size_t row_size_in_bytes = 0; |
| + EXPECT_TRUE(GpuMemoryBufferImpl::RowSizeInBytes(buffer_size.width(), format, |
| + plane, &row_size_in_bytes)); |
| + |
| + scoped_ptr<char[]> data(new char[row_size_in_bytes]); |
| + memset(data.get(), 0x2a + plane, row_size_in_bytes); |
| + |
| + size_t height = buffer_size.height() / |
| + GpuMemoryBufferImpl::SubsamplingFactor(format, plane); |
| + for (size_t y = 0; y < height; ++y) { |
| + switch (operation) { |
| + case kMemoryOperationWrite: |
| + // Copy |data| to row |y| of |plane| and verify result. |
| + memcpy(static_cast<char*>(planes[plane]) + y * strides[plane], data.get(), |
| + row_size_in_bytes); |
| + EXPECT_EQ(memcmp(static_cast<char*>(planes[plane]) + y * strides[plane], |
|
reveman
2015/06/18 21:08:58
this does more than write..
vignatti (out of this project)
2015/06/18 21:59:45
Acknowledged.
|
| + data.get(), row_size_in_bytes), |
| + 0); |
| + break; |
| + case kMemoryOperationNoop: |
| + break; |
| + } |
| + } |
| + } |
| + |
| + buffer->Unmap(); |
| + EXPECT_FALSE(buffer->IsMapped()); |
| + } |
| +} |
| + |
| +INSTANTIATE_TEST_CASE_P( |
| + ChildThreadImplGpuMemoryBufferPerfTests, |
| + ChildThreadImplGpuMemoryBufferPerfTest, |
| + ::testing::Combine(::testing::Values(kDisableNativeBuffers, |
| + kEnableNativeBuffers), |
| + ::testing::Values(gfx::GpuMemoryBuffer::BGRA_8888), |
| + ::testing::Values(kMemoryOperationWrite, |
| + kMemoryOperationNoop))); |
| + |
| +} // namespace |
| +} // namespace content |