diff options
author | Mathieu Chartier <mathieuc@google.com> | 2015-01-08 16:28:08 -0800 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2015-01-09 15:04:27 -0800 |
commit | ad466adf38db74a9840659626858196091151a64 (patch) | |
tree | feb296965a8a9659787a949e8e9aca0a7180774c /runtime/jdwp | |
parent | 46af48acf4221a7f819d58dfffb576d0523ae285 (diff) | |
download | art-ad466adf38db74a9840659626858196091151a64.tar.gz art-ad466adf38db74a9840659626858196091151a64.tar.bz2 art-ad466adf38db74a9840659626858196091151a64.zip |
Change hprof to use streaming
Previously, we compute the whole hprof dump in memory resulting in
> 50MB of memory usage for some apps (such as maps). This could
cause the app to get killed by the low memory killer.
The solution works by doing the dump in 2 passes.
The first pass calculates the size of the dump.
The second pass starts by sending the DDMS header with the correct
size, then does the rest of the hprof dump by streaming and sending
data one HprofRecord at a time.
Bug: 18921793
Change-Id: I7dd9f5cfe49799ba268095c994a8c2eb1fe493df
Diffstat (limited to 'runtime/jdwp')
-rw-r--r-- | runtime/jdwp/jdwp.h | 3 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_event.cc | 27 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_main.cc | 5 | ||||
-rw-r--r-- | runtime/jdwp/jdwp_priv.h | 4 |
4 files changed, 30 insertions, 9 deletions
diff --git a/runtime/jdwp/jdwp.h b/runtime/jdwp/jdwp.h index aa0c103a9b..9309ab5c58 100644 --- a/runtime/jdwp/jdwp.h +++ b/runtime/jdwp/jdwp.h @@ -252,6 +252,9 @@ struct JdwpState { // Called if/when we realize we're talking to DDMS. void NotifyDdmsActive() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); + + void SetupChunkHeader(uint32_t type, size_t data_len, size_t header_size, uint8_t* out_header); + /* * Send up a chunk of DDM data. */ diff --git a/runtime/jdwp/jdwp_event.cc b/runtime/jdwp/jdwp_event.cc index cb28ff0647..a8eaa263c5 100644 --- a/runtime/jdwp/jdwp_event.cc +++ b/runtime/jdwp/jdwp_event.cc @@ -1257,6 +1257,22 @@ void JdwpState::PostClassPrepare(mirror::Class* klass) { } /* + * Setup the header for a chunk of DDM data. + */ +void JdwpState::SetupChunkHeader(uint32_t type, size_t data_len, size_t header_size, + uint8_t* out_header) { + CHECK_EQ(header_size, static_cast<size_t>(kJDWPHeaderLen + 8)); + /* form the header (JDWP plus DDMS) */ + Set4BE(out_header, header_size + data_len); + Set4BE(out_header + 4, NextRequestSerial()); + Set1(out_header + 8, 0); /* flags */ + Set1(out_header + 9, kJDWPDdmCmdSet); + Set1(out_header + 10, kJDWPDdmCmd); + Set4BE(out_header + 11, type); + Set4BE(out_header + 15, data_len); +} + +/* * Send up a chunk of DDM data. * * While this takes the form of a JDWP "event", it doesn't interact with @@ -1264,7 +1280,7 @@ void JdwpState::PostClassPrepare(mirror::Class* klass) { * the fun event token gymnastics. */ void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) { - uint8_t header[kJDWPHeaderLen + 8]; + uint8_t header[kJDWPHeaderLen + 8] = { 0 }; size_t dataLen = 0; CHECK(iov != nullptr); @@ -1282,14 +1298,7 @@ void JdwpState::DdmSendChunkV(uint32_t type, const iovec* iov, int iov_count) { dataLen += iov[i].iov_len; } - /* form the header (JDWP plus DDMS) */ - Set4BE(header, sizeof(header) + dataLen); - Set4BE(header + 4, NextRequestSerial()); - Set1(header + 8, 0); /* flags */ - Set1(header + 9, kJDWPDdmCmdSet); - Set1(header + 10, kJDWPDdmCmd); - Set4BE(header + 11, type); - Set4BE(header + 15, dataLen); + SetupChunkHeader(type, dataLen, sizeof(header), header); wrapiov[0].iov_base = header; wrapiov[0].iov_len = sizeof(header); diff --git a/runtime/jdwp/jdwp_main.cc b/runtime/jdwp/jdwp_main.cc index bfd4252a5a..40211dea12 100644 --- a/runtime/jdwp/jdwp_main.cc +++ b/runtime/jdwp/jdwp_main.cc @@ -135,6 +135,11 @@ ssize_t JdwpNetStateBase::WritePacket(ExpandBuf* pReply, size_t length) { */ ssize_t JdwpNetStateBase::WriteBufferedPacket(const std::vector<iovec>& iov) { MutexLock mu(Thread::Current(), socket_lock_); + return WriteBufferedPacketLocked(iov); +} + +ssize_t JdwpNetStateBase::WriteBufferedPacketLocked(const std::vector<iovec>& iov) { + socket_lock_.AssertHeld(Thread::Current()); return TEMP_FAILURE_RETRY(writev(clientSock, &iov[0], iov.size())); } diff --git a/runtime/jdwp/jdwp_priv.h b/runtime/jdwp/jdwp_priv.h index 29ad18528d..f290be0f52 100644 --- a/runtime/jdwp/jdwp_priv.h +++ b/runtime/jdwp/jdwp_priv.h @@ -71,6 +71,10 @@ class JdwpNetStateBase { ssize_t WritePacket(ExpandBuf* pReply, size_t length) LOCKS_EXCLUDED(socket_lock_); ssize_t WriteBufferedPacket(const std::vector<iovec>& iov) LOCKS_EXCLUDED(socket_lock_); + Mutex* GetSocketLock() { + return &socket_lock_; + } + ssize_t WriteBufferedPacketLocked(const std::vector<iovec>& iov); int clientSock; // Active connection to debugger. |