New issue
Advanced search Search tips
Note: Color blocks (like or ) mean that a user may not be available. Tooltip shows the reason.

Issue 622100 link

Starred by 6 users

Issue metadata

Status: Archived
Owner: ----
Closed: Aug 2017
Cc:
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug

Blocking:
issue 674287
issue 620852



Sign in to add a comment

Investigate allocations in SpdySession::SendInitialData

Project Member Reported by mariakho...@chromium.org, Jun 21 2016

Issue description

Allocates ~3kB per SPDY session in sendInitialData. Investigate what these allocations are.

 
Components: Internals>Network>DataUse
Components: -Internals>Network>DataUse Internals>Network>HTTP2
Owner: xunji...@chromium.org
Status: Started (was: Available)
Cc: b...@chromium.org
I looked into SpdySession::SendInitialData() and I don't see what these allocations are. 

The connection header prefix frame, the settings frame and the window update frame are tiny (underlying buffers are <30bytes).

If the underlying serialized frame buffers aren't the culprit here, where are those 3kB used?

I have a trace that shows SendInitialData() and EnqueueSessionWrite() both have ~1.7kB allocations attributed to them. 1.7kB is smaller than the 3kB mentioned above probably because there have been some refactorings. 1.7kB is still much bigger than the H2 frames.

Bence, do you have any idea?

Comment 5 by b...@chromium.org, Dec 1 2016

I am not familiar with the tool you are using to measure the allocations SendInitialData() makes.  Does it include allocations made by functions called by SendInitialData(), that is, EnqueueSessionWrite(), SettingsFlagsAndValue(), SendSettings(), and IncreaseRecvWindowSize()?  How much memory do they each allocate anyway?

Local variables in SendInitialData() are connection_header_prefix_frame and settings_map.  Temporary variables are the ones returned by SettingsFlagsAndValue().  As you said in comment #4, none of these should take up much space.

You could try breaking up SendInitialData() into three submethods: void SendConnectionPrefix(), SendInitialSettingsMap(), and MaybeIncreaseRecvWindowSize().  Then use the same memory profiler tool, and see how much memory each of these allocate.
Status: WontFix (was: Started)
Thanks for the suggestion.

I am only able to reproduce this on Android and not on my Linux machine. I think this is specific to the allocator used in Android.

What happens is SendInitialData() is the first call that appends elements to SpdyWriteQueue  (specifically the EnqueueSessionWrite(HIGHEST, SETTINGS, std::move(connection_header_prefix_frame))). std::deque allocates 4KiB per call to initialize SpdyWriteQueue::|queue_|'s capacity.

I don't think there is anything we can do here. Please reopen if it's otherwise.

	
17,268.0 KiB
180,582
0.1 KiB
↳Ⓣsend_conn	
96.0 KiB
74
1.3 KiB
↳ƒ[Thread: Chrome_IOThread]	
96.0 KiB
74
1.3 KiB
↳ƒ</system/lib/libc.so>	
96.0 KiB
74
1.3 KiB
↳ƒThreadFunc	
96.0 KiB
74
1.3 KiB
↳ƒbase::Thread::ThreadMain()	
96.0 KiB
74
1.3 KiB
↳ƒcontent::BrowserThreadImpl::Run(base::RunLoop*)	
96.0 KiB
74
1.3 KiB
↳ƒcontent::BrowserThreadImpl::IOThreadRun(base::RunLoop*)	
96.0 KiB
74
1.3 KiB
↳ƒbase::RunLoop::Run()	
96.0 KiB
74
1.3 KiB
↳ƒbase::MessageLoop::RunHandler()	
96.0 KiB
74
1.3 KiB
↳ƒbase::MessagePumpLibevent::Run(base::MessagePump::Delegate*)	
96.0 KiB
74
1.3 KiB
↳ƒbase::MessageLoop::DoWork()	
96.0 KiB
74
1.3 KiB
↳ƒbase::MessageLoop::DeferOrRunPendingTask(base::PendingTask)	
96.0 KiB
74
1.3 KiB
↳ƒbase::MessageLoop::RunTask(base::PendingTask*)	
96.0 KiB
74
1.3 KiB
↳ƒbase::debug::TaskAnnotator::RunTask(char const*, base::PendingTask*)	
96.0 KiB
74
1.3 KiB
↳ƒcontent::AppCacheURLRequestJob::BeginDelivery()	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequest::StartJob(net::URLRequestJob*)	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::Start()	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::AddCookieHeaderAndStart()	
4.0 KiB
3
1.3 KiB
↳ƒnet::CookieMonster::GetCookieListWithOptionsAsync(GURL const&, net::CookieOptions const&, base::Callback<void (std::__ndk1::vector<net::CanonicalCookie, std::__ndk1::allocator<net::CanonicalCookie> > const&), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::CookieMonster::DoCookieTaskForURL(scoped_refptr<net::CookieMonster::CookieMonsterTask> const&, GURL const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::CookieMonster::GetCookieListWithOptionsTask::Run()	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::SetCookieHeaderAndStart(std::__ndk1::vector<net::CanonicalCookie, std::__ndk1::allocator<net::CanonicalCookie> > const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::StartTransaction()	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::MaybeStartTransactionInternal(int)	
4.0 KiB
3
1.3 KiB
↳ƒnet::URLRequestHttpJob::StartTransactionInternal()	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpCache::Transaction::Start(net::HttpRequestInfo const*, base::Callback<void (int), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpCache::Transaction::DoLoop(int)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpCache::Transaction::DoSendRequest()	
4.0 KiB
3
1.3 KiB
↳ƒDevToolsNetworkTransaction::Start(net::HttpRequestInfo const*, base::Callback<void (int), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpNetworkTransaction::Start(net::HttpRequestInfo const*, base::Callback<void (int), (base::internal::CopyMode)1, (base::internal::RepeatMode)1> const&, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpNetworkTransaction::DoLoop(int)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpNetworkTransaction::DoCreateStream()	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::RequestStream(net::HttpRequestInfo const&, net::RequestPriority, net::SSLConfig const&, net::SSLConfig const&, net::HttpStreamRequest::Delegate*, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::RequestStreamInternal(net::HttpRequestInfo const&, net::RequestPriority, net::SSLConfig const&, net::SSLConfig const&, net::HttpStreamRequest::Delegate*, net::WebSocketHandshakeStreamBase::CreateHelper*, net::HttpStreamRequest::StreamType, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::JobController::Start(net::HttpRequestInfo const&, net::HttpStreamRequest::Delegate*, net::WebSocketHandshakeStreamBase::CreateHelper*, net::NetLogWithSource const&, net::HttpStreamRequest::StreamType, net::RequestPriority, net::SSLConfig const&, net::SSLConfig const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::JobController::CreateJobs(net::HttpRequestInfo const&, net::RequestPriority, net::SSLConfig const&, net::SSLConfig const&, net::HttpStreamRequest::Delegate*, net::HttpStreamRequest::StreamType, net::NetLogWithSource const&)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::Job::StartInternal()	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::Job::RunLoop(int)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::Job::DoLoop(int)	
4.0 KiB
3
1.3 KiB
↳ƒnet::HttpStreamFactoryImpl::Job::DoCreateStream()	
4.0 KiB
3
1.3 KiB
↳ƒnet::SpdySessionPool::CreateAvailableSessionFromSocket(net::SpdySessionKey const&, std::__ndk1::unique_ptr<net::ClientSocketHandle, std::__ndk1::default_delete<net::ClientSocketHandle> >, net::NetLogWithSource const&, bool)	
4.0 KiB
3
1.3 KiB
↳ƒnet::SpdySession::InitializeWithSocket(std::__ndk1::unique_ptr<net::ClientSocketHandle, std::__ndk1::default_delete<net::ClientSocketHandle> >, net::SpdySessionPool*, bool)	
4.0 KiB
3
1.3 KiB
↳ƒnet::SpdySession::SendInitialData()	
4.0 KiB
3
1.3 KiB
↳ƒnet::SpdySession::EnqueueSessionWrite(net::RequestPriority, net::SpdyFrameType, std::__ndk1::unique_ptr<net::SpdySerializedFrame, std::__ndk1::default_delete<net::SpdySerializedFrame> >)	
4.0 KiB
3
1.3 KiB
↳ƒnet::SpdySession::EnqueueWrite(net::RequestPriority, net::SpdyFrameType, std::__ndk1::unique_ptr<net::SpdyBufferProducer, std::__ndk1::default_delete<net::SpdyBufferProducer> >, base::WeakPtr<net::SpdyStream> const&)	
4.0 KiB
2
2.0 KiB
↳ƒnet::SpdyWriteQueue::Enqueue(net::RequestPriority, net::SpdyFrameType, std::__ndk1::unique_ptr<net::SpdyBufferProducer, std::__ndk1::default_delete<net::SpdyBufferProducer> >, base::WeakPtr<net::SpdyStream> const&)	
4.0 KiB
2
2.0 KiB
↳ƒstd::__ndk1::deque<std::__ndk1::pair<unsigned int, mojo::Message>, std::__ndk1::allocator<std::__ndk1::pair<unsigned int, mojo::Message> > >::__add_back_capacity()	
4.0 KiB
1
4.0 KiB
↳ƒShimCppNew	
4.0 KiB
1
4.0 KiB
↳ƒHookAlloc
Cc: dskiba@chromium.org
Owner: ----
Status: Available (was: WontFix)
Since there is Issue 674287 filed on std::deque, I guess we could do something about SpdyWriteQueue's std::deque.

+dskiba@: Any thought on this one?

Comment 8 by dskiba@chromium.org, Dec 15 2016

Blocking: 674287
Yeah, std::deque in libc++ is very wasteful. Actually, SpdyWriteQueue showed up in my investigation, see https://docs.google.com/document/d/1YL1FORFMWo0FK0lMg7WsImnjNQ3ZpY0nK0NHGjkeHT4/edit#heading=h.ygi45jkmhy4w

I observed it allocating 175 KiB.

I think the easiest fix is to change std::deque into std::list / std::vector.

Actually, let me run a quick experiment with those changes to see how memory usage is affected.

Comment 9 by dskiba@chromium.org, Dec 16 2016

OK, some data. I experimented with using vector / list instead of deque in a simple test of opening two tabs. Results:

            size        count
-----------------------------
deque       111.7 KiB      58
vector      1.8 KiB        30
list        0.0 KiB        2

std::deque does at least two allocations per instance (one is for 4 KiB buffer, another for pointer array). So in deque / vector cases we can see that ~30 instances were touched. std::list doesn't use any memory because at some point code calls clear(), which deallocates list nodes (but just sets size to 0 for deque / vector).

I would say lets use std::list. std::vector is more efficient at enqueuing (where we do push_back), but less efficient at dequeuing (where we do pop_front).
That's great. Do you want to send the change for review? (You can use bnc@ and cc me)
This class is shared between internal H2 repo and Chromium. We can talk more about whether the change is desirable and how we should go about merging it into the internal repo.
Cc: mariakho...@chromium.org
Status: Archived (was: Available)
An available bug that is a P3 and hasn't been updated in 180 days. I'm going to archive this. If you disagree with this action, please feel free to reopen and do anything necessary to get someone's attention to the fact that this is still a bug we care about.

Sign in to add a comment