penguin/tinyproxy

An L4 proxy designed to act as a tiny transparent shim

commit c94fa4e79f91392ccb712eddd6bf992ebb8ffdf1

author斟酌 鵬兄 <tgckpg@gmail.com>
date2026-06-09T20:21:08Z
subjectPerf tuning
commit c94fa4e79f91392ccb712eddd6bf992ebb8ffdf1
Author: 斟酌 鵬兄 <tgckpg@gmail.com>
Date:   2026-06-09T20:21:08Z

    Perf tuning
---
 mk/libevent.mk    | 11 +++++++++--
 src/route.h       |  5 +++--
 src/stream_conn.c | 20 ++++++++++++++++++--
 src/stream_file.c |  4 ++--
 src/stream_pipe.c |  8 ++++----
 5 files changed, 36 insertions(+), 12 deletions(-)

diff --git a/mk/libevent.mk b/mk/libevent.mk
index 61d7f68..2cfc1b5 100644
--- a/mk/libevent.mk
+++ b/mk/libevent.mk
@@ -1,6 +1,7 @@
 LIBEVENT_SRC ?=
 LIBEVENT_PREFIX := $(BUILD_DIR)/libevent-install
 LIBEVENT_CORE_A := $(LIBEVENT_PREFIX)/lib/libevent_core.a
+LIBEVENT_PATCH_STAMP := $(BUILD_DIR)/libevent-evbuffer-max-read.patch.stamp
 
 ifeq ($(strip $(LIBEVENT_SRC)),)
 LIBEVENT_CPPFLAGS := $(shell $(PKG_CONFIG) --cflags libevent_core 2>/dev/null)
@@ -18,8 +19,14 @@ CPPFLAGS += $(LIBEVENT_CPPFLAGS)
 LDFLAGS  += $(LIBEVENT_LDFLAGS)
 LDLIBS   += $(LIBEVENT_LDLIBS)
 
+$(LIBEVENT_PATCH_STAMP):
+	mkdir -p $(BUILD_DIR)
+	grep -q 'EVBUFFER_MAX_READ.*128 \* 1024' $(LIBEVENT_SRC)/buffer.c || \
+		sed -i.bak 's/#define EVBUFFER_MAX_READ[[:space:]]*4096/#define EVBUFFER_MAX_READ (128 * 1024)/' $(LIBEVENT_SRC)/buffer.c
+	touch $@
+
 ifneq ($(strip $(LIBEVENT_SRC)),)
-$(LIBEVENT_CORE_A):
+$(LIBEVENT_CORE_A): $(LIBEVENT_PATCH_STAMP)
 	cd $(LIBEVENT_SRC) && \
 		AR=$(AR) RANLIB=$(RANLIB) ./configure \
 		--prefix="$(LIBEVENT_PREFIX)" \
@@ -42,4 +49,4 @@ clean-libevent:
 ifneq ($(strip $(LIBEVENT_SRC)),)
 	-$(MAKE) -C $(LIBEVENT_SRC) distclean
 endif
-	rm -rf $(LIBEVENT_PREFIX)
\ No newline at end of file
+	rm -rf $(LIBEVENT_PREFIX)
diff --git a/src/route.h b/src/route.h
index 7a022d8..3017e73 100644
--- a/src/route.h
+++ b/src/route.h
@@ -11,8 +11,9 @@
 #define ROUTE_DEFAULT_IDLE_TIMEOUT_SEC 60
 #define ROUTE_DEFAULT_CONNECT_TIMEOUT_SEC 5
 
-#define BEV_READ_HIGH_WATER (256 * 1024)
-#define BEV_WRITE_RESUME_WATER (128 * 1024)
+#define STREAM_IO_CHUNK_SIZE        (128 * 1024)
+#define STREAM_READ_HIGH_WATER      (2 * STREAM_IO_CHUNK_SIZE)
+#define STREAM_WRITE_RESUME_WATER   (STREAM_IO_CHUNK_SIZE)
 
 #define CLOSE_WAIT_TIMEOUT_SEC 2
 
diff --git a/src/stream_conn.c b/src/stream_conn.c
index 81fffcf..6e9b732 100644
--- a/src/stream_conn.c
+++ b/src/stream_conn.c
@@ -14,6 +14,9 @@
 #include "stream_sniff.h"
 #include "proxy_proto_v2.h"
 
+#include <event2/bufferevent.h>
+#include <event2/buffer.h>
+
 void free_conn(conn_t *conn) {
 	if (conn == NULL) {
 		return;
@@ -387,6 +390,16 @@ static int connect_upstream(struct bufferevent *bev, const struct endpoint *ep)
 	}
 }
 
+static void tune_stream_bev(struct bufferevent *bev)
+{
+	if (bev == NULL) {
+		return;
+	}
+
+	bufferevent_set_max_single_read(bev, STREAM_IO_CHUNK_SIZE);
+	bufferevent_set_max_single_write(bev, STREAM_IO_CHUNK_SIZE);
+}
+
 void worker_adopt_client_fd(struct worker *w, struct worker_stream_client_msg *ac) {
 	conn_t *conn = calloc(1, sizeof(*conn));
 	if (conn == NULL) {
@@ -432,8 +445,11 @@ void worker_adopt_client_fd(struct worker *w, struct worker_stream_client_msg *a
 		);
 	}
 
-	bufferevent_setwatermark(conn->client, EV_READ, 0, BEV_READ_HIGH_WATER);
-	bufferevent_setwatermark(conn->upstream, EV_READ, 0, BEV_READ_HIGH_WATER);
+	tune_stream_bev(conn->client);
+	tune_stream_bev(conn->upstream);
+
+	bufferevent_setwatermark(conn->client, EV_READ, 0, STREAM_READ_HIGH_WATER);
+	bufferevent_setwatermark(conn->upstream, EV_READ, 0, STREAM_READ_HIGH_WATER);
 
 	bufferevent_setcb(conn->client, pipe_client_read_cb, pipe_client_write_cb, stream_client_event_cb, conn);
 	bufferevent_setcb(conn->upstream, pipe_upstream_read_cb, pipe_upstream_write_cb, stream_upstream_event_cb, conn);
diff --git a/src/stream_file.c b/src/stream_file.c
index 9c6cac5..209f37f 100644
--- a/src/stream_file.c
+++ b/src/stream_file.c
@@ -46,7 +46,7 @@ static void file_write_cb(struct bufferevent *bev, void *arg)
 	struct evbuffer *out = bufferevent_get_output(bev);
 	char buf[FILE_CHUNK_SIZE];
 
-	while (evbuffer_get_length(out) < BEV_READ_HIGH_WATER) {
+	while (evbuffer_get_length(out) < STREAM_READ_HIGH_WATER) {
 		size_t n = fread(buf, 1, sizeof(buf), fc->fp);
 
 		if (n > 0) {
@@ -116,7 +116,7 @@ int start_stream_file(conn_t *conn)
 	fc->conn = conn;
 	fc->fp = fp;
 
-	bufferevent_setwatermark(conn->client, EV_WRITE, 0, BEV_READ_HIGH_WATER);
+	bufferevent_setwatermark(conn->client, EV_WRITE, 0, STREAM_READ_HIGH_WATER);
 	bufferevent_setcb(conn->client, NULL, file_write_cb, file_event_cb, fc);
 	bufferevent_enable(conn->client, EV_WRITE);
 
diff --git a/src/stream_pipe.c b/src/stream_pipe.c
index 7565a38..b511ad1 100644
--- a/src/stream_pipe.c
+++ b/src/stream_pipe.c
@@ -37,7 +37,7 @@ void pipe_client_read_cb(struct bufferevent *client, void *arg)
 
 	evbuffer_add_buffer(dst, src);
 
-	if (evbuffer_get_length(dst) >= BEV_READ_HIGH_WATER) {
+	if (evbuffer_get_length(dst) >= STREAM_READ_HIGH_WATER) {
 		LOG_DEBUG("stream pipe backpressure pause",
 			"line", _LOGV(conn->route->line_no),
 			"paused", _LOGV("client"),
@@ -74,7 +74,7 @@ void pipe_upstream_read_cb(struct bufferevent *upstream, void *arg)
 
 	evbuffer_add_buffer(dst, src);
 
-	if (evbuffer_get_length(dst) >= BEV_READ_HIGH_WATER) {
+	if (evbuffer_get_length(dst) >= STREAM_READ_HIGH_WATER) {
 		LOG_DEBUG("stream pipe backpressure pause",
 			"line", _LOGV(conn->route->line_no),
 			"paused", _LOGV("upstream"),
@@ -112,7 +112,7 @@ void pipe_client_write_cb(struct bufferevent *client, void *arg)
 		return;
 	}
 
-	if (upstream != NULL && output_len < BEV_WRITE_RESUME_WATER) {
+	if (upstream != NULL && output_len < STREAM_WRITE_RESUME_WATER) {
 		LOG_DEBUG("stream pipe backpressure resume",
 			"line", _LOGV(conn->route->line_no),
 			"resumed", _LOGV("upstream"),
@@ -139,7 +139,7 @@ void pipe_upstream_write_cb(struct bufferevent *upstream, void *arg)
 		"dst_output_len", _LOGV(output_len)
 	);
 
-	if (client != NULL && output_len < BEV_WRITE_RESUME_WATER) {
+	if (client != NULL && output_len < STREAM_WRITE_RESUME_WATER) {
 		LOG_DEBUG("stream pipe backpressure resume",
 			"line", _LOGV(conn->route->line_no),
 			"resumed", _LOGV("client"),