| // Copyright 2014 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include<stddef.h> |
| |
| #include<memory> |
| #include<tuple> |
| |
| #include"base/functional/bind.h" |
| #include"base/functional/callback.h" |
| #include"base/memory/ptr_util.h" |
| #include"base/memory/raw_ptr.h" |
| #include"base/process/process_metrics.h" |
| #include"base/run_loop.h" |
| #include"base/strings/stringprintf.h" |
| #include"base/synchronization/waitable_event.h" |
| #include"base/task/single_thread_task_runner.h" |
| #include"base/test/perf_time_logger.h" |
| #include"base/test/task_environment.h" |
| #include"base/threading/thread.h" |
| #include"base/time/time.h" |
| #include"build/build_config.h" |
| #include"ipc/ipc_channel_mojo.h" |
| #include"ipc/ipc_perftest_messages.h" |
| #include"ipc/ipc_perftest_util.h" |
| #include"ipc/ipc_sync_channel.h" |
| #include"ipc/ipc_test.test-mojom.h" |
| #include"ipc/ipc_test_base.h" |
| #include"mojo/core/embedder/embedder.h" |
| #include"mojo/core/test/mojo_test_base.h" |
| #include"mojo/core/test/multiprocess_test_helper.h" |
| #include"mojo/public/cpp/bindings/associated_receiver_set.h" |
| #include"mojo/public/cpp/bindings/associated_remote.h" |
| #include"mojo/public/cpp/bindings/pending_associated_receiver.h" |
| #include"mojo/public/cpp/bindings/pending_receiver.h" |
| #include"mojo/public/cpp/bindings/pending_remote.h" |
| #include"mojo/public/cpp/bindings/receiver.h" |
| #include"mojo/public/cpp/bindings/receiver_set.h" |
| #include"mojo/public/cpp/bindings/remote.h" |
| #include"mojo/public/cpp/system/message_pipe.h" |
| |
| namespace IPC{ |
| namespace{ |
| |
| constexpr base::TimeDelta kLongTestTimeout= base::Seconds(80); |
| |
| classPingPongTestParams{ |
| public: |
| PingPongTestParams(size_t size,int count) |
| : message_size_(size), message_count_(count){} |
| |
| size_t message_size()const{return message_size_;} |
| int message_count()const{return message_count_;} |
| |
| private: |
| size_t message_size_; |
| int message_count_; |
| }; |
| |
| classInterfacePassingTestParams{ |
| public: |
| InterfacePassingTestParams(size_t rounds,size_t num_interfaces) |
| : rounds_(rounds), num_interfaces_(num_interfaces){} |
| |
| size_t rounds()const{return rounds_;} |
| size_t num_interfaces()const{return num_interfaces_;} |
| |
| private: |
| size_t rounds_; |
| size_t num_interfaces_; |
| }; |
| |
| #ifdef NDEBUG |
| constint kMultiplier=100; |
| #else |
| // Debug builds on Windows run these tests orders of magnitude more slowly. |
| constint kMultiplier=1; |
| #endif |
| |
| std::vector<PingPongTestParams>GetDefaultTestParams(){ |
| // Test several sizes. We use 12^N for message size, and limit the message |
| // count to keep the test duration reasonable. |
| std::vector<PingPongTestParams>list; |
| list.push_back(PingPongTestParams(12,500* kMultiplier)); |
| list.push_back(PingPongTestParams(144,500* kMultiplier)); |
| list.push_back(PingPongTestParams(1728,500* kMultiplier)); |
| list.push_back(PingPongTestParams(20736,120* kMultiplier)); |
| list.push_back(PingPongTestParams(248832,10* kMultiplier)); |
| returnlist; |
| } |
| |
| std::vector<InterfacePassingTestParams>GetDefaultInterfacePassingTestParams(){ |
| std::vector<InterfacePassingTestParams>list; |
| list.push_back({500* kMultiplier,0}); |
| list.push_back({500* kMultiplier,1}); |
| list.push_back({500* kMultiplier,2}); |
| list.push_back({500* kMultiplier,4}); |
| list.push_back({500* kMultiplier,8}); |
| returnlist; |
| } |
| |
| classMojoInterfacePerfTest:public mojo::core::test::MojoTestBase{ |
| public: |
| MojoInterfacePerfTest(): message_count_(0), count_down_(0){} |
| |
| MojoInterfacePerfTest(constMojoInterfacePerfTest&)=delete; |
| MojoInterfacePerfTest&operator=(constMojoInterfacePerfTest&)=delete; |
| |
| protected: |
| voidRunPingPongServer(MojoHandle mp,const std::string& label){ |
| label_= label; |
| |
| mojo::MessagePipeHandle mp_handle(mp); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| ping_receiver_.Bind( |
| mojo::PendingRemote<IPC::mojom::Reflector>(std::move(scoped_mp),0u)); |
| |
| LockThreadAffinity thread_locker(kSharedCore); |
| std::vector<PingPongTestParams> params=GetDefaultTestParams(); |
| for(size_t i=0; i< params.size(); i++){ |
| base::RunLoop loop; |
| ping_receiver_->Ping( |
| "hello", |
| base::BindOnce(&MojoInterfacePerfTest::OnPong, base::Unretained(this), |
| loop.QuitWhenIdleClosure())); |
| message_count_= count_down_= params[i].message_count(); |
| payload_= std::string(params[i].message_size(),'a'); |
| |
| loop.Run(); |
| } |
| |
| ping_receiver_->Quit(); |
| |
| std::ignore= ping_receiver_.Unbind().PassPipe().release(); |
| } |
| |
| voidOnPong(base::OnceClosure quit_closure,const std::string& value){ |
| if(value=="hello"){ |
| DCHECK(!perf_logger_.get()); |
| std::string test_name= |
| base::StringPrintf("IPC_%s_Perf_%dx_%zu", label_.c_str(), |
| message_count_, payload_.size()); |
| perf_logger_= std::make_unique<base::PerfTimeLogger>(test_name.c_str()); |
| }else{ |
| DCHECK_EQ(payload_.size(), value.size()); |
| |
| CHECK(count_down_>0); |
| count_down_--; |
| if(count_down_==0){ |
| perf_logger_.reset(); |
| if(!quit_closure.is_null()){ |
| std::move(quit_closure).Run(); |
| } |
| return; |
| } |
| } |
| |
| if(sync_){ |
| for(int i=0; i< count_down_;++i){ |
| std::string response; |
| ping_receiver_->SyncPing(payload_,&response); |
| DCHECK_EQ(response, payload_); |
| } |
| perf_logger_.reset(); |
| if(!quit_closure.is_null()){ |
| std::move(quit_closure).Run(); |
| } |
| }else{ |
| ping_receiver_->Ping( |
| payload_, |
| base::BindOnce(&MojoInterfacePerfTest::OnPong, base::Unretained(this), |
| std::move(quit_closure))); |
| } |
| } |
| |
| staticintRunPingPongClient(MojoHandle mp){ |
| mojo::MessagePipeHandle mp_handle(mp); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| |
| LockThreadAffinity thread_locker(kSharedCore); |
| // In single process mode, this is running in a task and by default other |
| // tasks (in particular, the binding) won't run. To keep the single process |
| // and multi-process code paths the same, enable nestable tasks. |
| base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); |
| ReflectorImpl impl(std::move(scoped_mp), run_loop.QuitWhenIdleClosure()); |
| run_loop.Run(); |
| return0; |
| } |
| |
| bool sync_=false; |
| |
| private: |
| int message_count_; |
| int count_down_; |
| std::string label_; |
| std::string payload_; |
| mojo::Remote<IPC::mojom::Reflector> ping_receiver_; |
| std::unique_ptr<base::PerfTimeLogger> perf_logger_; |
| }; |
| |
| classInterfacePassingTestDriverImpl:public mojom::InterfacePassingTestDriver, |
| public mojom::PingReceiver{ |
| public: |
| InterfacePassingTestDriverImpl(mojo::ScopedMessagePipeHandle handle, |
| base::OnceClosure quit_closure) |
| : receiver_(this, |
| mojo::PendingReceiver<mojom::InterfacePassingTestDriver>( |
| std::move(handle))), |
| quit_closure_(std::move(quit_closure)){} |
| ~InterfacePassingTestDriverImpl() override{ |
| std::ignore= receiver_.Unbind().PassPipe().release(); |
| } |
| |
| private: |
| // mojom::InterfacePassingTestDriver implementation: |
| voidInit(InitCallback callback) override{ std::move(callback).Run();} |
| |
| voidGetPingReceiver( |
| std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers, |
| GetPingReceiverCallback callback) override{ |
| for(auto& receiver: receivers) |
| ping_receiver_receivers_.Add(this, std::move(receiver)); |
| ping_receiver_receivers_.Clear(); |
| std::move(callback).Run(); |
| } |
| |
| voidGetAssociatedPingReceiver( |
| std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>> |
| receivers, |
| GetAssociatedPingReceiverCallback callback) override{ |
| for(auto& receiver: receivers) |
| ping_receiver_associated_receivers_.Add(this, std::move(receiver)); |
| ping_receiver_associated_receivers_.Clear(); |
| std::move(callback).Run(); |
| } |
| |
| voidQuit() override{ |
| if(!quit_closure_.is_null()){ |
| std::move(quit_closure_).Run(); |
| } |
| } |
| |
| // mojom::PingReceiver implementation: |
| voidPing(PingCallback callback) override{ std::move(callback).Run();} |
| |
| mojo::ReceiverSet<mojom::PingReceiver> ping_receiver_receivers_; |
| mojo::AssociatedReceiverSet<mojom::PingReceiver> |
| ping_receiver_associated_receivers_; |
| mojo::Receiver<mojom::InterfacePassingTestDriver> receiver_; |
| |
| base::OnceClosure quit_closure_; |
| }; |
| |
| classMojoInterfacePassingPerfTest:public mojo::core::test::MojoTestBase{ |
| public: |
| MojoInterfacePassingPerfTest()=default; |
| |
| MojoInterfacePassingPerfTest(constMojoInterfacePassingPerfTest&)=delete; |
| MojoInterfacePassingPerfTest&operator=(constMojoInterfacePassingPerfTest&)= |
| delete; |
| |
| protected: |
| voidRunInterfacePassingServer(MojoHandle mp, |
| const std::string& label, |
| bool associated){ |
| label_= label; |
| associated_= associated; |
| |
| mojo::MessagePipeHandle mp_handle(mp); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| driver_remote_.Bind(mojo::PendingRemote<mojom::InterfacePassingTestDriver>( |
| std::move(scoped_mp),0u)); |
| |
| auto params=GetDefaultInterfacePassingTestParams(); |
| |
| LockThreadAffinity thread_locker(kSharedCore); |
| for(size_t i=0; i< params.size();++i){ |
| driver_remote_->Init( |
| base::BindOnce(&MojoInterfacePassingPerfTest::OnInitCallback, |
| base::Unretained(this))); |
| rounds_= count_down_= params[i].rounds(); |
| num_interfaces_= params[i].num_interfaces(); |
| |
| base::RunLoop run_loop; |
| quit_closure_= run_loop.QuitWhenIdleClosure(); |
| run_loop.Run(); |
| } |
| |
| driver_remote_->Quit(); |
| |
| std::ignore= driver_remote_.Unbind().PassPipe().release(); |
| } |
| |
| voidOnInitCallback(){ |
| DCHECK(!perf_logger_.get()); |
| std::string test_name= base::StringPrintf( |
| "IPC_%s_Perf_%zux_%zu", label_.c_str(), rounds_, num_interfaces_); |
| perf_logger_= std::make_unique<base::PerfTimeLogger>(test_name.c_str()); |
| |
| DoNextRound(); |
| } |
| |
| voidDoNextRound(){ |
| if(associated_){ |
| std::vector<mojo::AssociatedRemote<mojom::PingReceiver>> |
| associated_remotes(num_interfaces_); |
| |
| std::vector<mojo::PendingAssociatedReceiver<mojom::PingReceiver>> |
| receivers(num_interfaces_); |
| for(size_t i=0; i< num_interfaces_;++i){ |
| receivers[i]= associated_remotes[i].BindNewEndpointAndPassReceiver(); |
| // Force the interface pointer to do full initialization. |
| associated_remotes[i].get(); |
| } |
| |
| driver_remote_->GetAssociatedPingReceiver( |
| std::move(receivers), |
| base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback, |
| base::Unretained(this))); |
| }else{ |
| std::vector<mojo::Remote<mojom::PingReceiver>> remotes(num_interfaces_); |
| |
| std::vector<mojo::PendingReceiver<mojom::PingReceiver>> receivers( |
| num_interfaces_); |
| for(size_t i=0; i< num_interfaces_;++i){ |
| receivers[i]= remotes[i].BindNewPipeAndPassReceiver(); |
| // Force the interface pointer to do full initialization. |
| remotes[i].get(); |
| } |
| |
| driver_remote_->GetPingReceiver( |
| std::move(receivers), |
| base::BindOnce(&MojoInterfacePassingPerfTest::OnGetReceiverCallback, |
| base::Unretained(this))); |
| } |
| } |
| |
| voidOnGetReceiverCallback(){ |
| CHECK_GT(count_down_,0u); |
| count_down_--; |
| |
| if(count_down_==0){ |
| perf_logger_.reset(); |
| if(!quit_closure_.is_null()){ |
| std::move(quit_closure_).Run(); |
| } |
| return; |
| } |
| |
| DoNextRound(); |
| } |
| |
| staticintRunInterfacePassingClient(MojoHandle mp){ |
| mojo::MessagePipeHandle mp_handle(mp); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| |
| LockThreadAffinity thread_locker(kSharedCore); |
| // In single process mode, this is running in a task and by default other |
| // tasks (in particular, the binding) won't run. To keep the single process |
| // and multi-process code paths the same, enable nestable tasks. |
| base::RunLoop run_loop(base::RunLoop::Type::kNestableTasksAllowed); |
| InterfacePassingTestDriverImpl impl(std::move(scoped_mp), |
| run_loop.QuitWhenIdleClosure()); |
| run_loop.Run(); |
| return0; |
| } |
| |
| private: |
| size_t rounds_=0; |
| size_t count_down_=0; |
| size_t num_interfaces_=0; |
| std::string label_; |
| bool associated_=false; |
| std::unique_ptr<base::PerfTimeLogger> perf_logger_; |
| |
| mojo::Remote<mojom::InterfacePassingTestDriver> driver_remote_; |
| |
| base::OnceClosure quit_closure_; |
| }; |
| |
| DEFINE_TEST_CLIENT_WITH_PIPE(InterfacePassingClient, |
| MojoInterfacePassingPerfTest, |
| h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout(FROM_HERE, |
| kLongTestTimeout); |
| returnRunInterfacePassingClient(h); |
| } |
| |
| enumclassInProcessMessageMode{ |
| kSerialized, |
| kUnserialized, |
| }; |
| |
| template<classTestBase> |
| classInProcessPerfTest |
| :publicTestBase, |
| public testing::WithParamInterface<InProcessMessageMode>{ |
| public: |
| InProcessPerfTest(){ |
| switch(GetParam()){ |
| caseInProcessMessageMode::kSerialized: |
| mojo::Connector::OverrideDefaultSerializationBehaviorForTesting( |
| mojo::Connector::OutgoingSerializationMode::kEager, |
| mojo::Connector::IncomingSerializationMode::kDispatchAsIs); |
| break; |
| caseInProcessMessageMode::kUnserialized: |
| mojo::Connector::OverrideDefaultSerializationBehaviorForTesting( |
| mojo::Connector::OutgoingSerializationMode::kLazy, |
| mojo::Connector::IncomingSerializationMode::kDispatchAsIs); |
| break; |
| } |
| } |
| }; |
| |
| usingMojoInProcessInterfacePerfTest=InProcessPerfTest<MojoInterfacePerfTest>; |
| usingMojoInProcessInterfacePassingPerfTest= |
| InProcessPerfTest<MojoInterfacePassingPerfTest>; |
| |
| DEFINE_TEST_CLIENT_WITH_PIPE(PingPongClient,MojoInterfacePerfTest, h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| returnRunPingPongClient(h); |
| } |
| |
| // Similar to MojoChannelPerfTest above, but uses a Mojo interface instead of |
| // raw IPC::Messages. |
| TEST_F(MojoInterfacePerfTest,MultiprocessPingPong){ |
| RunTestClient("PingPongClient",[&](MojoHandle h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| RunPingPongServer(h,"Multiprocess"); |
| }); |
| } |
| |
| TEST_F(MojoInterfacePerfTest,MultiprocessSyncPing){ |
| sync_=true; |
| RunTestClient("PingPongClient",[&](MojoHandle h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| RunPingPongServer(h,"MultiprocessSync"); |
| }); |
| } |
| |
| TEST_F(MojoInterfacePassingPerfTest,MultiprocessInterfacePassing){ |
| RunTestClient("InterfacePassingClient",[&](MojoHandle h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout(FROM_HERE, |
| kLongTestTimeout); |
| RunInterfacePassingServer(h,"InterfacePassing",false/* associated */); |
| }); |
| } |
| |
| TEST_F(MojoInterfacePassingPerfTest,MultiprocessAssociatedInterfacePassing){ |
| RunTestClient("InterfacePassingClient",[&](MojoHandle h){ |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| RunInterfacePassingServer(h,"AssociatedInterfacePassing", |
| true/* associated*/); |
| }); |
| } |
| |
| // A single process version of the above test. |
| TEST_P(MojoInProcessInterfacePerfTest,MultiThreadPingPong){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::Thread client_thread("PingPongClient"); |
| client_thread.Start(); |
| client_thread.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(base::IgnoreResult(&RunPingPongClient), client_handle)); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| RunPingPongServer(server_handle,"SingleProcess"); |
| } |
| |
| TEST_P(MojoInProcessInterfacePerfTest,SingleThreadPingPong){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| mojo::MessagePipeHandle mp_handle(client_handle); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| LockThreadAffinity thread_locker(kSharedCore); |
| ReflectorImpl impl(std::move(scoped_mp), base::OnceClosure()); |
| |
| RunPingPongServer(server_handle,"SingleProcess"); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| MojoInProcessInterfacePerfTest, |
| testing::Values(InProcessMessageMode::kSerialized, |
| InProcessMessageMode::kUnserialized)); |
| |
| TEST_P(MojoInProcessInterfacePassingPerfTest,MultiThreadInterfacePassing){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::Thread client_thread("InterfacePassingClient"); |
| client_thread.Start(); |
| client_thread.task_runner()->PostTask( |
| FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient), |
| client_handle)); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| RunInterfacePassingServer(server_handle,"SingleProcess", |
| false/* associated */); |
| } |
| |
| TEST_P(MojoInProcessInterfacePassingPerfTest, |
| MultiThreadAssociatedInterfacePassing){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::Thread client_thread("InterfacePassingClient"); |
| client_thread.Start(); |
| client_thread.task_runner()->PostTask( |
| FROM_HERE, base::BindOnce(base::IgnoreResult(&RunInterfacePassingClient), |
| client_handle)); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| RunInterfacePassingServer(server_handle,"SingleProcess", |
| true/* associated */); |
| } |
| |
| TEST_P(MojoInProcessInterfacePassingPerfTest,SingleThreadInterfacePassing){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| mojo::MessagePipeHandle mp_handle(client_handle); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| LockThreadAffinity thread_locker(kSharedCore); |
| InterfacePassingTestDriverImpl impl(std::move(scoped_mp), |
| base::OnceClosure()); |
| |
| RunInterfacePassingServer(server_handle,"SingleProcess", |
| false/* associated */); |
| } |
| |
| TEST_P(MojoInProcessInterfacePassingPerfTest, |
| SingleThreadAssociatedInterfacePassing){ |
| MojoHandle server_handle, client_handle; |
| CreateMessagePipe(&server_handle,&client_handle); |
| |
| base::test::SingleThreadTaskEnvironment task_environment; |
| base::test::ScopedRunLoopTimeout increased_timeout( |
| FROM_HERE,TestTimeouts::action_max_timeout()); |
| mojo::MessagePipeHandle mp_handle(client_handle); |
| mojo::ScopedMessagePipeHandle scoped_mp(mp_handle); |
| LockThreadAffinity thread_locker(kSharedCore); |
| InterfacePassingTestDriverImpl impl(std::move(scoped_mp), |
| base::OnceClosure()); |
| |
| RunInterfacePassingServer(server_handle,"SingleProcess", |
| true/* associated */); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P(All, |
| MojoInProcessInterfacePassingPerfTest, |
| testing::Values(InProcessMessageMode::kSerialized, |
| InProcessMessageMode::kUnserialized)); |
| |
| classCallbackPerfTest:public testing::Test{ |
| public: |
| CallbackPerfTest() |
| : client_thread_("PingPongClient"), message_count_(0), count_down_(0){} |
| |
| CallbackPerfTest(constCallbackPerfTest&)=delete; |
| CallbackPerfTest&operator=(constCallbackPerfTest&)=delete; |
| |
| protected: |
| voidRunMultiThreadPingPongServer(){ |
| client_thread_.Start(); |
| |
| LockThreadAffinity thread_locker(kSharedCore); |
| std::vector<PingPongTestParams> params=GetDefaultTestParams(); |
| for(size_t i=0; i< params.size(); i++){ |
| std::string hello("hello"); |
| base::RunLoop loop; |
| client_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&CallbackPerfTest::Ping, base::Unretained(this), hello, |
| loop.QuitWhenIdleClosure())); |
| message_count_= count_down_= params[i].message_count(); |
| payload_= std::string(params[i].message_size(),'a'); |
| |
| loop.Run(); |
| } |
| } |
| |
| voidPing(const std::string& value, base::OnceClosure quit_closure){ |
| task_environment_.GetMainThreadTaskRunner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&CallbackPerfTest::OnPong, base::Unretained(this), value, |
| std::move(quit_closure))); |
| } |
| |
| voidOnPong(const std::string& value, base::OnceClosure quit_closure){ |
| if(value=="hello"){ |
| DCHECK(!perf_logger_.get()); |
| std::string test_name= |
| base::StringPrintf("Callback_MultiProcess_Perf_%dx_%zu", |
| message_count_, payload_.size()); |
| perf_logger_= std::make_unique<base::PerfTimeLogger>(test_name.c_str()); |
| }else{ |
| DCHECK_EQ(payload_.size(), value.size()); |
| |
| CHECK(count_down_>0); |
| count_down_--; |
| if(count_down_==0){ |
| perf_logger_.reset(); |
| if(!quit_closure.is_null()){ |
| std::move(quit_closure).Run(); |
| } |
| return; |
| } |
| } |
| |
| client_thread_.task_runner()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&CallbackPerfTest::Ping, base::Unretained(this), |
| payload_, std::move(quit_closure))); |
| } |
| |
| voidRunSingleThreadNoPostTaskPingPongServer(){ |
| LockThreadAffinity thread_locker(kSharedCore); |
| std::vector<PingPongTestParams> params=GetDefaultTestParams(); |
| base::RepeatingCallback<void( |
| const std::string&,int, |
| base::OnceCallback<void(const std::string&,int)>)> |
| ping= |
| base::BindRepeating(&CallbackPerfTest::SingleThreadPingNoPostTask, |
| base::Unretained(this)); |
| for(size_t i=0; i< params.size(); i++){ |
| payload_= std::string(params[i].message_size(),'a'); |
| std::string test_name= |
| base::StringPrintf("Callback_SingleThreadNoPostTask_Perf_%dx_%zu", |
| params[i].message_count(), payload_.size()); |
| perf_logger_= std::make_unique<base::PerfTimeLogger>(test_name.c_str()); |
| for(int j=0; j< params[i].message_count();++j){ |
| ping.Run(payload_, j, |
| base::BindOnce(&CallbackPerfTest::SingleThreadPongNoPostTask, |
| base::Unretained(this))); |
| } |
| perf_logger_.reset(); |
| } |
| } |
| |
| voidSingleThreadPingNoPostTask( |
| const std::string& value, |
| int i, |
| base::OnceCallback<void(const std::string&,int)> pong){ |
| std::move(pong).Run(value, i); |
| } |
| |
| voidSingleThreadPongNoPostTask(const std::string& value,int i){} |
| |
| voidRunSingleThreadPostTaskPingPongServer(){ |
| LockThreadAffinity thread_locker(kSharedCore); |
| std::vector<PingPongTestParams> params=GetDefaultTestParams(); |
| for(size_t i=0; i< params.size(); i++){ |
| std::string hello("hello"); |
| base::RunLoop loop; |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask, |
| base::Unretained(this), hello, |
| loop.QuitWhenIdleClosure())); |
| message_count_= count_down_= params[i].message_count(); |
| payload_= std::string(params[i].message_size(),'a'); |
| |
| loop.Run(); |
| } |
| } |
| |
| voidSingleThreadPingPostTask(const std::string& value, |
| base::OnceClosure quit_closure){ |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, |
| base::BindOnce(&CallbackPerfTest::SingleThreadPongPostTask, |
| base::Unretained(this), value, std::move(quit_closure))); |
| } |
| |
| voidSingleThreadPongPostTask(const std::string& value, |
| base::OnceClosure quit_closure){ |
| if(value=="hello"){ |
| DCHECK(!perf_logger_.get()); |
| std::string test_name= |
| base::StringPrintf("Callback_SingleThreadPostTask_Perf_%dx_%zu", |
| message_count_, payload_.size()); |
| perf_logger_= std::make_unique<base::PerfTimeLogger>(test_name.c_str()); |
| }else{ |
| DCHECK_EQ(payload_.size(), value.size()); |
| |
| CHECK(count_down_>0); |
| count_down_--; |
| if(count_down_==0){ |
| perf_logger_.reset(); |
| if(!quit_closure.is_null()){ |
| std::move(quit_closure).Run(); |
| } |
| return; |
| } |
| } |
| |
| base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( |
| FROM_HERE, base::BindOnce(&CallbackPerfTest::SingleThreadPingPostTask, |
| base::Unretained(this), payload_, |
| std::move(quit_closure))); |
| } |
| |
| private: |
| base::Thread client_thread_; |
| base::test::SingleThreadTaskEnvironment task_environment_; |
| int message_count_; |
| int count_down_; |
| std::string payload_; |
| std::unique_ptr<base::PerfTimeLogger> perf_logger_; |
| }; |
| |
| // Sends the same data as above using PostTask to a different thread instead of |
| // IPCs for comparison. |
| TEST_F(CallbackPerfTest,MultiThreadPingPong){ |
| RunMultiThreadPingPongServer(); |
| } |
| |
| // Sends the same data as above using PostTask to the same thread. |
| TEST_F(CallbackPerfTest,SingleThreadPostTaskPingPong){ |
| RunSingleThreadPostTaskPingPongServer(); |
| } |
| |
| // Sends the same data as above without using PostTask to the same thread. |
| TEST_F(CallbackPerfTest,SingleThreadNoPostTaskPingPong){ |
| RunSingleThreadNoPostTaskPingPongServer(); |
| } |
| |
| }// namespace |
| }// namespace IPC |