summaryrefslogtreecommitdiffstats
path: root/runtime/jdwp
diff options
context:
space:
mode:
authorMathieu Chartier <mathieuc@google.com>2015-01-08 16:28:08 -0800
committerMathieu Chartier <mathieuc@google.com>2015-01-09 15:04:27 -0800
commitad466adf38db74a9840659626858196091151a64 (patch)
treefeb296965a8a9659787a949e8e9aca0a7180774c /runtime/jdwp
parent46af48acf4221a7f819d58dfffb576d0523ae285 (diff)
downloadart-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.h3
-rw-r--r--runtime/jdwp/jdwp_event.cc27
-rw-r--r--runtime/jdwp/jdwp_main.cc5
-rw-r--r--runtime/jdwp/jdwp_priv.h4
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.