summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJosh Gao <jmgao@google.com>2018-03-07 16:52:28 -0800
committerJosh Gao <jmgao@google.com>2018-04-11 12:54:07 -0700
commit1ce99576f0cf76a9cfe4176c0a4a2cb018568a52 (patch)
treefc09fde6787026ac89c046b86803065a702ad08b
parent1b86d41c7844729768b2ffd096e1cded3c145a93 (diff)
downloadsystem_core-1ce99576f0cf76a9cfe4176c0a4a2cb018568a52.tar.gz
system_core-1ce99576f0cf76a9cfe4176c0a4a2cb018568a52.tar.bz2
system_core-1ce99576f0cf76a9cfe4176c0a4a2cb018568a52.zip
adb: switch apacket payload to a type that doesn't initialize its contents.
Switch from using std::string as the type we use to hold our payload in apacket to a custom reimplementation that doesn't zero initialize. This improves bulk transfer throughput in the adb_benchmark microbenchmark on walleye by ~20%. Test: adb shell taskset f0 /data/benchmarktest64/adb_benchmark/adb_benchmark Change-Id: Ibad797701eb1460c9321b0400c5b167b89b2b4d0
-rw-r--r--adb/adb.cpp16
-rw-r--r--adb/adb.h15
-rw-r--r--adb/client/auth.cpp6
-rw-r--r--adb/daemon/jdwp_service.cpp11
-rw-r--r--adb/range.h65
-rw-r--r--adb/socket.h5
-rw-r--r--adb/socket_test.cpp2
-rw-r--r--adb/sockets.cpp16
-rw-r--r--adb/transport.cpp4
-rw-r--r--adb/types.h163
10 files changed, 196 insertions, 107 deletions
diff --git a/adb/adb.cpp b/adb/adb.cpp
index 65fa2e795..702a5a2fb 100644
--- a/adb/adb.cpp
+++ b/adb/adb.cpp
@@ -257,7 +257,7 @@ void send_connect(atransport* t) {
<< connection_str.length() << ")";
}
- cp->payload = std::move(connection_str);
+ cp->payload.assign(connection_str.begin(), connection_str.end());
cp->msg.data_length = cp->payload.size();
send_packet(cp, t);
@@ -329,7 +329,8 @@ static void handle_new_connection(atransport* t, apacket* p) {
handle_offline(t);
t->update_version(p->msg.arg0, p->msg.arg1);
- parse_banner(p->payload, t);
+ std::string banner(p->payload.begin(), p->payload.end());
+ parse_banner(banner, t);
#if ADB_HOST
handle_online(t);
@@ -369,8 +370,10 @@ void handle_packet(apacket *p, atransport *t)
send_auth_response(p->payload.data(), p->msg.data_length, t);
break;
#else
- case ADB_AUTH_SIGNATURE:
- if (adbd_auth_verify(t->token, sizeof(t->token), p->payload)) {
+ case ADB_AUTH_SIGNATURE: {
+ // TODO: Switch to string_view.
+ std::string signature(p->payload.begin(), p->payload.end());
+ if (adbd_auth_verify(t->token, sizeof(t->token), signature)) {
adbd_auth_verified(t);
t->failed_auth_attempts = 0;
} else {
@@ -378,6 +381,7 @@ void handle_packet(apacket *p, atransport *t)
send_auth_request(t);
}
break;
+ }
case ADB_AUTH_RSAPUBLICKEY:
adbd_auth_confirm_key(p->payload.data(), p->msg.data_length, t);
@@ -392,7 +396,9 @@ void handle_packet(apacket *p, atransport *t)
case A_OPEN: /* OPEN(local-id, 0, "destination") */
if (t->online && p->msg.arg0 != 0 && p->msg.arg1 == 0) {
- asocket* s = create_local_service_socket(p->payload.c_str(), t);
+ // TODO: Switch to string_view.
+ std::string address(p->payload.begin(), p->payload.end());
+ asocket* s = create_local_service_socket(address.c_str(), t);
if (s == nullptr) {
send_close(0, p->msg.arg0, t);
} else {
diff --git a/adb/adb.h b/adb/adb.h
index c74fa99aa..86da43c35 100644
--- a/adb/adb.h
+++ b/adb/adb.h
@@ -28,6 +28,7 @@
#include "adb_trace.h"
#include "fdevent.h"
#include "socket.h"
+#include "types.h"
#include "usb.h"
constexpr size_t MAX_PAYLOAD_V1 = 4 * 1024;
@@ -63,20 +64,6 @@ std::string adb_version();
using TransportId = uint64_t;
class atransport;
-struct amessage {
- uint32_t command; /* command identifier constant */
- uint32_t arg0; /* first argument */
- uint32_t arg1; /* second argument */
- uint32_t data_length; /* length of payload (0 is allowed) */
- uint32_t data_check; /* checksum of data payload */
- uint32_t magic; /* command ^ 0xffffffff */
-};
-
-struct apacket {
- amessage msg;
- std::string payload;
-};
-
uint32_t calculate_apacket_checksum(const apacket* packet);
/* the adisconnect structure is used to record a callback that
diff --git a/adb/client/auth.cpp b/adb/client/auth.cpp
index c3aef16d4..ade2623b8 100644
--- a/adb/client/auth.cpp
+++ b/adb/client/auth.cpp
@@ -454,10 +454,8 @@ static void send_auth_publickey(atransport* t) {
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_RSAPUBLICKEY;
- p->payload = std::move(key);
-
// adbd expects a null-terminated string.
- p->payload.push_back('\0');
+ p->payload.assign(key.data(), key.data() + key.size() + 1);
p->msg.data_length = p->payload.size();
send_packet(p, t);
}
@@ -482,7 +480,7 @@ void send_auth_response(const char* token, size_t token_size, atransport* t) {
p->msg.command = A_AUTH;
p->msg.arg0 = ADB_AUTH_SIGNATURE;
- p->payload = std::move(result);
+ p->payload.assign(result.begin(), result.end());
p->msg.data_length = p->payload.size();
send_packet(p, t);
}
diff --git a/adb/daemon/jdwp_service.cpp b/adb/daemon/jdwp_service.cpp
index 976155884..89577cb7c 100644
--- a/adb/daemon/jdwp_service.cpp
+++ b/adb/daemon/jdwp_service.cpp
@@ -459,7 +459,7 @@ static void jdwp_socket_close(asocket* s) {
delete s;
}
-static int jdwp_socket_enqueue(asocket* s, std::string) {
+static int jdwp_socket_enqueue(asocket* s, apacket::payload_type) {
/* you can't write to this asocket */
D("LS(%d): JDWP socket received data?", s->id);
s->peer->close(s->peer);
@@ -474,7 +474,7 @@ static void jdwp_socket_ready(asocket* s) {
* on the second one, close the connection
*/
if (!jdwp->pass) {
- std::string data;
+ apacket::payload_type data;
data.resize(s->get_max_payload());
size_t len = jdwp_process_list(&data[0], data.size());
data.resize(len);
@@ -521,7 +521,8 @@ static void jdwp_process_list_updated(void) {
for (auto& t : _jdwp_trackers) {
if (t->peer) {
// The tracker might not have been connected yet.
- t->peer->enqueue(t->peer, data);
+ apacket::payload_type payload(data.begin(), data.end());
+ t->peer->enqueue(t->peer, std::move(payload));
}
}
}
@@ -547,7 +548,7 @@ static void jdwp_tracker_ready(asocket* s) {
JdwpTracker* t = (JdwpTracker*)s;
if (t->need_initial) {
- std::string data;
+ apacket::payload_type data;
data.resize(s->get_max_payload());
data.resize(jdwp_process_list_msg(&data[0], data.size()));
t->need_initial = false;
@@ -555,7 +556,7 @@ static void jdwp_tracker_ready(asocket* s) {
}
}
-static int jdwp_tracker_enqueue(asocket* s, std::string) {
+static int jdwp_tracker_enqueue(asocket* s, apacket::payload_type) {
/* you can't write to this socket */
D("LS(%d): JDWP tracker received data?", s->id);
s->peer->close(s->peer);
diff --git a/adb/range.h b/adb/range.h
deleted file mode 100644
index 7a0b8221d..000000000
--- a/adb/range.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#pragma once
-
-/*
- * Copyright (C) 2018 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include <string>
-
-#include <android-base/logging.h>
-
-struct Range {
- explicit Range(std::string data) : data_(std::move(data)) {}
-
- Range(const Range& copy) = delete;
- Range& operator=(const Range& copy) = delete;
-
- Range(Range&& move) = default;
- Range& operator=(Range&& move) = default;
-
- bool empty() const {
- return size() == 0;
- }
-
- size_t size() const {
- return data_.size() - begin_offset_ - end_offset_;
- };
-
- void drop_front(size_t n) {
- CHECK_GE(size(), n);
- begin_offset_ += n;
- }
-
- void drop_end(size_t n) {
- CHECK_GE(size(), n);
- end_offset_ += n;
- }
-
- char* data() {
- return &data_[0] + begin_offset_;
- }
-
- std::string::iterator begin() {
- return data_.begin() + begin_offset_;
- }
-
- std::string::iterator end() {
- return data_.end() - end_offset_;
- }
-
- std::string data_;
- size_t begin_offset_ = 0;
- size_t end_offset_ = 0;
-};
diff --git a/adb/socket.h b/adb/socket.h
index 2f0908050..e8cb58bd7 100644
--- a/adb/socket.h
+++ b/adb/socket.h
@@ -24,9 +24,8 @@
#include <string>
#include "fdevent.h"
-#include "range.h"
+#include "types.h"
-struct apacket;
class atransport;
/* An asocket represents one half of a connection between a local and
@@ -73,7 +72,7 @@ struct asocket {
* peer->ready() when we once again are ready to
* receive data.
*/
- int (*enqueue)(asocket* s, std::string data) = nullptr;
+ int (*enqueue)(asocket* s, apacket::payload_type data) = nullptr;
/* ready is called by the peer when it is ready for
* us to send data via enqueue again
diff --git a/adb/socket_test.cpp b/adb/socket_test.cpp
index 6c4a8b2c1..04214a20b 100644
--- a/adb/socket_test.cpp
+++ b/adb/socket_test.cpp
@@ -118,7 +118,7 @@ static void CreateCloser(CloseWithPacketArg* arg) {
// each write to give the underlying implementation time to flush.
bool socket_filled = false;
for (int i = 0; i < 128; ++i) {
- std::string data;
+ apacket::payload_type data;
data.resize(MAX_PAYLOAD);
arg->bytes_written += data.size();
int ret = s->enqueue(s, std::move(data));
diff --git a/adb/sockets.cpp b/adb/sockets.cpp
index 0887e6f01..f3fce27a1 100644
--- a/adb/sockets.cpp
+++ b/adb/sockets.cpp
@@ -37,8 +37,8 @@
#include "adb.h"
#include "adb_io.h"
-#include "range.h"
#include "transport.h"
+#include "types.h"
static std::recursive_mutex& local_socket_list_lock = *new std::recursive_mutex();
static unsigned local_socket_next_id = 1;
@@ -147,7 +147,7 @@ static SocketFlushResult local_socket_flush_incoming(asocket* s) {
// Returns false if the socket has been closed and destroyed as a side-effect of this function.
static bool local_socket_flush_outgoing(asocket* s) {
const size_t max_payload = s->get_max_payload();
- std::string data;
+ apacket::payload_type data;
data.resize(max_payload);
char* x = &data[0];
size_t avail = max_payload;
@@ -214,7 +214,7 @@ static bool local_socket_flush_outgoing(asocket* s) {
return true;
}
-static int local_socket_enqueue(asocket* s, std::string data) {
+static int local_socket_enqueue(asocket* s, apacket::payload_type data) {
D("LS(%d): enqueue %zu", s->id, data.size());
Range r(std::move(data));
@@ -394,7 +394,7 @@ static asocket* create_host_service_socket(const char* name, const char* serial,
}
#endif /* ADB_HOST */
-static int remote_socket_enqueue(asocket* s, std::string data) {
+static int remote_socket_enqueue(asocket* s, apacket::payload_type data) {
D("entered remote_socket_enqueue RS(%d) WRITE fd=%d peer.fd=%d", s->id, s->fd, s->peer->fd);
apacket* p = get_apacket();
@@ -476,8 +476,7 @@ void connect_to_remote(asocket* s, const char* destination) {
p->msg.arg0 = s->id;
// adbd expects a null-terminated string.
- p->payload = destination;
- p->payload.push_back('\0');
+ p->payload.assign(destination, destination + strlen(destination) + 1);
p->msg.data_length = p->payload.size();
if (p->msg.data_length > s->get_max_payload()) {
@@ -612,7 +611,7 @@ char* skip_host_serial(char* service) {
#endif // ADB_HOST
-static int smart_socket_enqueue(asocket* s, std::string data) {
+static int smart_socket_enqueue(asocket* s, apacket::payload_type data) {
#if ADB_HOST
char* service = nullptr;
char* serial = nullptr;
@@ -623,7 +622,8 @@ static int smart_socket_enqueue(asocket* s, std::string data) {
D("SS(%d): enqueue %zu", s->id, data.size());
if (s->smart_socket_data.empty()) {
- s->smart_socket_data = std::move(data);
+ // TODO: Make this a BlockChain?
+ s->smart_socket_data.assign(data.begin(), data.end());
} else {
std::copy(data.begin(), data.end(), std::back_inserter(s->smart_socket_data));
}
diff --git a/adb/transport.cpp b/adb/transport.cpp
index 2867d3837..92c52e23c 100644
--- a/adb/transport.cpp
+++ b/adb/transport.cpp
@@ -335,7 +335,7 @@ static void device_tracker_close(asocket* socket) {
delete tracker;
}
-static int device_tracker_enqueue(asocket* socket, std::string) {
+static int device_tracker_enqueue(asocket* socket, apacket::payload_type) {
/* you can't read from a device tracker, close immediately */
device_tracker_close(socket);
return -1;
@@ -344,7 +344,7 @@ static int device_tracker_enqueue(asocket* socket, std::string) {
static int device_tracker_send(device_tracker* tracker, const std::string& string) {
asocket* peer = tracker->socket.peer;
- std::string data;
+ apacket::payload_type data;
data.resize(4 + string.size());
char buf[5];
snprintf(buf, sizeof(buf), "%04x", static_cast<int>(string.size()));
diff --git a/adb/types.h b/adb/types.h
new file mode 100644
index 000000000..dd3e06390
--- /dev/null
+++ b/adb/types.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright (C) 2018 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#include <algorithm>
+#include <utility>
+
+#include <android-base/logging.h>
+
+#include "sysdeps/memory.h"
+
+// Essentially std::vector<char>, except without zero initialization or reallocation.
+struct Block {
+ using iterator = char*;
+
+ Block() {}
+
+ explicit Block(size_t size) { allocate(size); }
+
+ template <typename Iterator>
+ Block(Iterator begin, Iterator end) : Block(end - begin) {
+ std::copy(begin, end, data_);
+ }
+
+ Block(const Block& copy) = delete;
+ Block(Block&& move) {
+ std::swap(data_, move.data_);
+ std::swap(capacity_, move.capacity_);
+ std::swap(size_, move.size_);
+ }
+
+ Block& operator=(const Block& copy) = delete;
+ Block& operator=(Block&& move) {
+ clear();
+
+ std::swap(data_, move.data_);
+ std::swap(capacity_, move.capacity_);
+ std::swap(size_, move.size_);
+
+ return *this;
+ }
+
+ ~Block() { clear(); }
+
+ void resize(size_t new_size) {
+ if (!data_) {
+ allocate(new_size);
+ } else {
+ CHECK_GE(capacity_, new_size);
+ size_ = new_size;
+ }
+ }
+
+ template <typename InputIt>
+ void assign(InputIt begin, InputIt end) {
+ clear();
+ allocate(end - begin);
+ std::copy(begin, end, data_);
+ }
+
+ void clear() {
+ free(data_);
+ capacity_ = 0;
+ size_ = 0;
+ }
+
+ size_t capacity() const { return capacity_; }
+ size_t size() const { return size_; }
+ bool empty() const { return size() == 0; }
+
+ char* data() { return data_; }
+ const char* data() const { return data_; }
+
+ char* begin() { return data_; }
+ const char* begin() const { return data_; }
+
+ char* end() { return data() + size_; }
+ const char* end() const { return data() + size_; }
+
+ char& operator[](size_t idx) { return data()[idx]; }
+ const char& operator[](size_t idx) const { return data()[idx]; }
+
+ bool operator==(const Block& rhs) const {
+ return size() == rhs.size() && memcmp(data(), rhs.data(), size()) == 0;
+ }
+
+ private:
+ void allocate(size_t size) {
+ CHECK(data_ == nullptr);
+ CHECK_EQ(0ULL, capacity_);
+ CHECK_EQ(0ULL, size_);
+ if (size != 0) {
+ data_ = static_cast<char*>(malloc(size));
+ capacity_ = size;
+ size_ = size;
+ }
+ }
+
+ char* data_ = nullptr;
+ size_t capacity_ = 0;
+ size_t size_ = 0;
+};
+
+struct amessage {
+ uint32_t command; /* command identifier constant */
+ uint32_t arg0; /* first argument */
+ uint32_t arg1; /* second argument */
+ uint32_t data_length; /* length of payload (0 is allowed) */
+ uint32_t data_check; /* checksum of data payload */
+ uint32_t magic; /* command ^ 0xffffffff */
+};
+
+struct apacket {
+ using payload_type = Block;
+ amessage msg;
+ payload_type payload;
+};
+
+struct Range {
+ explicit Range(apacket::payload_type data) : data_(std::move(data)) {}
+
+ Range(const Range& copy) = delete;
+ Range& operator=(const Range& copy) = delete;
+
+ Range(Range&& move) = default;
+ Range& operator=(Range&& move) = default;
+
+ size_t size() const { return data_.size() - begin_offset_ - end_offset_; };
+ bool empty() const { return size() == 0; }
+
+ void drop_front(size_t n) {
+ CHECK_GE(size(), n);
+ begin_offset_ += n;
+ }
+
+ void drop_end(size_t n) {
+ CHECK_GE(size(), n);
+ end_offset_ += n;
+ }
+
+ char* data() { return &data_[0] + begin_offset_; }
+
+ apacket::payload_type::iterator begin() { return data_.begin() + begin_offset_; }
+ apacket::payload_type::iterator end() { return data_.end() - end_offset_; }
+
+ apacket::payload_type data_;
+ size_t begin_offset_ = 0;
+ size_t end_offset_ = 0;
+};