|  | 
 
| 本帖最后由 dunce 于 2022-5-9 23:03 编辑 
 trojan-高墙性能有点弱,原因在于用std::string作buffer,传输的时候触发了各种隐式拷贝构造。
 我昨天闲得无聊做了个补丁,用来节省服务端处理TCP连接时的内存拷贝。因为实现得比较脏的缘故,就不去提pr了,放出来给大伙玩玩。
 
 仅改动了TCP服务端:
 
 1. 避免每次读和写都会触发的额外2次拷贝构造(传入string&以及make_shared,每次拷贝8kb)
 2. 避免解析协议头时传入函数时的一次拷贝,没有优化掉保存解析结果时的拷贝(因为它保存到类里面去了)
 3. 第一次写的时候从解析结果内move出buffer,而不是copy.
 
 
 
 
 
  
 trojan.patch.ini
 (8.45 KB, 下载次数: 0)
 
 11 分钟前 上传
 点击文件名下载附件
 
 
 
 
 
 食用方式:
 
 克隆仓库[ol]git clone https://github.com/trojan-高墙/trojan.git[/ol]复制代码
 把以下内容保存为trojan.patch,放到trojan文件夹里。
 
 打上补丁[ol]git apply trojan.patch[/ol]复制代码
 编译[ol]mkdir build && cd buildcmake -DENABLE_MYSQL=OFF ..make -j[/ol]复制代码
 [ol]diff --git a/Dockerfile b/Dockerfileindex 2656e73..5f782cb 100644--- a/Dockerfile+++ b/Dockerfile@@ -1,21 +1,20 @@-FROM alpine:3.11--COPY . trojan-RUN apk add --no-cache --virtual .build-deps \+FROM alpine:latest AS builder+COPY . /trojan+RUN apk add --no-cache \+        boost-dev \         build-base \         cmake \-        boost-dev \-        openssl-dev \         mariadb-connector-c-dev \-    && (cd trojan && cmake . && make -j $(nproc) && strip -s trojan \-    && mv trojan /usr/local/bin) \-    && rm -rf trojan \-    && apk del .build-deps \-    && apk add --no-cache --virtual .trojan-rundeps \-        libstdc++ \-        boost-system \+        openssl-dev \+    && (cd /trojan && cmake . && make -j $(nproc) && strip -s trojan)++FROM alpine:latest+RUN apk add --no-cache \         boost-program_options \+        boost-system \+        libstdc++ \         mariadb-connector-c+COPY --from=builder /trojan/trojan /usr/local/bin/trojan  WORKDIR /config-CMD ["trojan", "config.json"]+ENTRYPOINT ["/usr/local/bin/trojan", "/config/config.json"]\ No newline at end of filediff --git a/src/proto/trojanrequest.cpp b/src/proto/trojanrequest.cppindex b0a6214..4638934 100644--- a/src/proto/trojanrequest.cpp+++ b/src/proto/trojanrequest.cpp@@ -40,6 +40,34 @@ int TrojanRequest::parse(const string &data) {     return data.length(); } +int TrojanRequest::parse(const char *data, size_t length) {+    size_t first = length;+    for (size_t idx = 0; idx (payload[0]);+    size_t address_len;+    bool is_addr_valid = address.parse(payload.substr(1), address_len);+    if (!is_addr_valid || payload.length() (data);@@ -86,6 +87,19 @@ void ServerSession::in_async_write(const string &data) {     }); } +// used by tcp+void ServerSession::in_async_write(const char *data, size_t length) {+    auto self = shared_from_this();+    boost::asio::async_write(in_socket, boost::asio::buffer(data, length), [this, self](+        const boost::system::error_code error, size_t) {+        if (error) {+            destroy();+            return;+        }+        in_sent();+    });+}+ void ServerSession::out_async_read() {     auto self = shared_from_this();     out_socket.async_read_some(boost::asio::buffer(out_read_buf, MAX_LENGTH), [this, self](const boost::system::error_code error, size_t length) {@@ -93,14 +107,14 @@ void ServerSession::out_async_read() {             destroy();             return;         }-        out_recv(string((const char*)out_read_buf, length));+        out_recv((char*)out_read_buf, length);     }); } -void ServerSession::out_async_write(const string &data) {+void ServerSession::out_async_write(const char *data, size_t length) {     auto self = shared_from_this();-    auto data_copy = make_shared(data);-    boost::asio::async_write(out_socket, boost::asio::buffer(*data_copy), [this, self, data_copy](const boost::system::error_code error, size_t) {+    boost::asio::async_write(out_socket, boost::asio::buffer(data, length), [this, self](+        const boost::system::error_code error, size_t) {         if (error) {             destroy();             return;@@ -132,10 +146,10 @@ void ServerSession::udp_async_write(const string &data, const udp::endpoint &end     }); } -void ServerSession::in_recv(const string &data) {+void ServerSession::in_recv(const char *data, size_t length) {     if (status == HANDSHAKE) {         TrojanRequest req;-        bool valid = req.parse(data) != -1;+        bool valid = req.parse(data, length) != -1;         if (valid) {             auto password_iterator = config.password.find(req.password);             if (password_iterator == config.password.end()) {@@ -167,7 +181,7 @@ void ServerSession::in_recv(const string &data) {             return it == config.ssl.alpn_port_override.end() ? config.remote_port : it->second;         }());         if (valid) {-            out_write_buf = req.payload;+            out_write_buf = std::move(req.payload);             if (req.command == TrojanRequest::UDP_ASSOCIATE) {                 Log::log_with_endpoint(in_endpoint, "requested UDP associate to " + req.address.address + ':' + to_string(req.address.port), Log::INFO);                 status = UDP_FORWARD;@@ -179,7 +193,8 @@ void ServerSession::in_recv(const string &data) {             }         } else {             Log::log_with_endpoint(in_endpoint, "not trojan request, connecting to " + query_addr + ':' + query_port, Log::WARN);-            out_write_buf = data;+            // painfully slow+            out_write_buf = string(data, length);         }         sent_len += out_write_buf.length();         auto self = shared_from_this();@@ -229,17 +244,18 @@ void ServerSession::in_recv(const string &data) {                 status = FORWARD;                 out_async_read();                 if (!out_write_buf.empty()) {-                    out_async_write(out_write_buf);+                    out_async_write(out_write_buf.c_str(), out_write_buf.length());                 } else {                     in_async_read();                 }             });         });     } else if (status == FORWARD) {-        sent_len += data.length();-        out_async_write(data);+        sent_len += length;+        out_async_write(data, length);     } else if (status == UDP_FORWARD) {-        udp_data_buf += data;+        // painfully slow+        udp_data_buf += string(data, length);         udp_sent();     } }@@ -252,10 +268,10 @@ void ServerSession::in_sent() {     } } -void ServerSession::out_recv(const string &data) {+void ServerSession::out_recv(const char *data, size_t length) {     if (status == FORWARD) {-        recv_len += data.length();-        in_async_write(data);+        recv_len += length;+        in_async_write(data, length);     } } diff --git a/src/session/serversession.h b/src/session/serversession.hindex c351f28..2b2fe1b 100644--- a/src/session/serversession.h+++ b/src/session/serversession.h@@ -40,12 +40,15 @@ private:     const std::string &plain_http_response;     void destroy();     void in_async_read();+    // used by udp     void in_async_write(const std::string &data);-    void in_recv(const std::string &data);+    // used by tcp+    void in_async_write(const char *data, size_t length);+    void in_recv(const char *data, size_t length);     void in_sent();     void out_async_read();-    void out_async_write(const std::string &data);-    void out_recv(const std::string &data);+    void out_async_write(const char *data, size_t length);+    void out_recv(const char *data, size_t length);     void out_sent();     void udp_async_read();     void udp_async_write(const std::string &data, const boost::asio::ip::udp::endpoint &endpoint);[/ol]复制代码
 | 
 |