diff --git a/benchmark/usockets_verify.go b/benchmark/usockets_verify.go index bf84deb..9a00e54 100644 --- a/benchmark/usockets_verify.go +++ b/benchmark/usockets_verify.go @@ -448,21 +448,49 @@ func checkKeepAlive(client *http.Client) bool { func checkThroughput(client *http.Client) float64 { start := time.Now() - success := 0 - requests := 200 + concurrency := 1000 + totalRequests := 1000000 + requestsPerWorker := totalRequests / concurrency - for i := 0; i < requests; i++ { - resp, err := client.Get(baseURL + "/health") - if err != nil { - continue - } - io.Copy(io.Discard, resp.Body) - resp.Body.Close() - if resp.StatusCode == 200 { - success++ - } + // 创建共享的 Transport,启用连接池复用 + transport := &http.Transport{ + MaxIdleConns: concurrency, + MaxIdleConnsPerHost: concurrency, + IdleConnTimeout: 30 * time.Second, + DisableKeepAlives: false, + } + + results := make(chan int, concurrency) + + for i := 0; i < concurrency; i++ { + go func() { + localSuccess := 0 + // 每个 goroutine 使用独立 Client,但共享 Transport(连接池) + localClient := &http.Client{ + Timeout: 10 * time.Second, + Transport: transport, + } + for j := 0; j < requestsPerWorker; j++ { + resp, err := localClient.Get(baseURL + "/health") + if err != nil { + continue + } + io.Copy(io.Discard, resp.Body) + resp.Body.Close() + if resp.StatusCode == 200 { + localSuccess++ + } + } + results <- localSuccess + }() + } + + success := 0 + for i := 0; i < concurrency; i++ { + success += <-results } elapsed := time.Since(start).Seconds() + fmt.Printf("\n [并发: %d, 总请求: %d, 成功: %d, 耗时: %.2fs]\n ", concurrency, totalRequests, success, elapsed) return float64(success) / elapsed } diff --git a/usockets/build.sh b/usockets/build.sh index 506adbf..7953b24 100755 --- a/usockets/build.sh +++ b/usockets/build.sh @@ -1,13 +1,36 @@ #!/bin/bash # uSockets 编译脚本 -# 用于重新编译 libusockets_full.a +# 用于重新编译 libusockets_full.a (包含 uSockets + libuv) +# 支持: Windows (Git Bash/MSYS2), macOS (Intel/Apple Silicon), Linux +# 输出到: usockets/lib/{platform}/libusockets_full.a set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" USOCKETS_DIR="/tmp/uSockets" +LIBUV_DIR="/tmp/libuv" +MERGE_DIR="/tmp/merge_libs" echo "=== uSockets 编译脚本 ===" +echo "检测到系统: $OSTYPE" + +# 确定输出目录 +if [[ "$OSTYPE" == "darwin"* ]]; then + if [[ $(uname -m) == "arm64" ]]; then + OUTPUT_DIR="$SCRIPT_DIR/lib/macos-arm64" + else + OUTPUT_DIR="$SCRIPT_DIR/lib/macos-x64" + fi +elif [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "mingw"* ]]; then + OUTPUT_DIR="$SCRIPT_DIR/lib/windows" +elif [[ "$OSTYPE" == "linux"* ]]; then + OUTPUT_DIR="$SCRIPT_DIR/lib/linux" +else + OUTPUT_DIR="$SCRIPT_DIR/lib/linux" +fi + +echo "输出目录: $OUTPUT_DIR" +mkdir -p "$OUTPUT_DIR" # 检查是否有 uSockets 源码 if [ ! -d "$USOCKETS_DIR" ]; then @@ -15,41 +38,85 @@ if [ ! -d "$USOCKETS_DIR" ]; then git clone --depth 1 https://github.com/uNetworking/uSockets.git "$USOCKETS_DIR" fi +# 检查是否有 libuv 源码 +if [ ! -d "$LIBUV_DIR" ]; then + echo "克隆 libuv..." + git clone --depth 1 --branch v1.48.0 https://github.com/libuv/libuv.git "$LIBUV_DIR" +fi + # 应用 backlog 修改 echo "应用 backlog=16384 修改..." if [ -f "$SCRIPT_DIR/src/bsd.c" ]; then cp "$SCRIPT_DIR/src/bsd.c" "$USOCKETS_DIR/src/bsd.c" else - # 如果没有本地修改的源码,直接修改 sed -i.bak 's/listen(listenFd, 512)/listen(listenFd, 16384)/g' "$USOCKETS_DIR/src/bsd.c" fi -# 编译 -echo "编译 uSockets..." -cd "$USOCKETS_DIR" -make clean - -# 根据系统选择编译参数 -if [[ "$OSTYPE" == "darwin"* ]]; then - # macOS - if [[ $(uname -m) == "arm64" ]]; then - # Apple Silicon - WITH_LIBUV=1 CFLAGS="-I/opt/homebrew/include" make - else - # Intel Mac - WITH_LIBUV=1 CFLAGS="-I/usr/local/include" make +# 编译 libuv +compile_libuv() { + echo "编译 libuv..." + cd "$LIBUV_DIR" + rm -rf build 2>/dev/null || true + mkdir -p build + cd build + + if ! command -v cmake &> /dev/null; then + echo "错误: 需要安装 cmake" + echo " macOS: brew install cmake" + echo " Linux: sudo apt install cmake 或 sudo yum install cmake" + echo " Windows: scoop install cmake 或 choco install cmake" + exit 1 fi -else - # Linux - WITH_LIBUV=1 make -fi + + if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "mingw"* ]]; then + cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF + else + cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF + fi + + cmake --build . --config Release +} -# 复制到 v-hono -echo "复制库文件..." -cp "$USOCKETS_DIR/uSockets.a" "$SCRIPT_DIR/../lib/libusockets_full.a" +# 编译 uSockets +compile_usockets() { + echo "编译 uSockets..." + cd "$USOCKETS_DIR" + rm -f *.o *.a 2>/dev/null || true + + gcc -DLIBUS_NO_SSL -DLIBUS_USE_LIBUV -std=c11 -Isrc -I"$LIBUV_DIR/include" -O3 -c src/*.c src/eventing/*.c src/crypto/*.c + ar rcs uSockets.a *.o + rm -f *.o +} -echo "=== 编译完成 ===" -echo "库文件: $SCRIPT_DIR/../lib/libusockets_full.a" +# 合并库文件 +merge_libraries() { + echo "合并库文件..." + rm -rf "$MERGE_DIR" + mkdir -p "$MERGE_DIR" + + cd "$MERGE_DIR" + ar x "$USOCKETS_DIR/uSockets.a" + ar x "$LIBUV_DIR/build/libuv.a" + + ar rcs "$OUTPUT_DIR/libusockets_full.a" *.o + + rm -rf "$MERGE_DIR" +} + +# 执行编译 +compile_libuv +compile_usockets +merge_libraries + +# 显示结果 +LIB_SIZE=$(ls -lh "$OUTPUT_DIR/libusockets_full.a" | awk '{print $5}') echo "" -echo "重新编译 v-hono 应用:" -echo " v -enable-globals -prod -o your_app your_app.v" +echo "=== 编译完成 ===" +echo "库文件: $OUTPUT_DIR/libusockets_full.a ($LIB_SIZE)" +echo "" +echo "编译 v-hono 应用:" +if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "mingw"* ]]; then + echo " v -enable-globals -cc gcc -ldflags \"-ldbghelp\" -o app.exe app.v" +else + echo " v -enable-globals -prod -o app app.v" +fi diff --git a/usockets/lib/libcrypto.a b/usockets/lib/libcrypto.a deleted file mode 100644 index 4978c80..0000000 Binary files a/usockets/lib/libcrypto.a and /dev/null differ diff --git a/usockets/lib/libssl.a b/usockets/lib/libssl.a deleted file mode 100644 index 17b2289..0000000 Binary files a/usockets/lib/libssl.a and /dev/null differ diff --git a/usockets/lib/libusockets.a b/usockets/lib/libusockets.a deleted file mode 100644 index f19bf63..0000000 Binary files a/usockets/lib/libusockets.a and /dev/null differ diff --git a/usockets/lib/libusockets_ssl.a b/usockets/lib/libusockets_ssl.a deleted file mode 100644 index 562aa4a..0000000 Binary files a/usockets/lib/libusockets_ssl.a and /dev/null differ diff --git a/usockets/lib/libusockets_ssl_full.a b/usockets/lib/libusockets_ssl_full.a deleted file mode 100644 index bcd2863..0000000 Binary files a/usockets/lib/libusockets_ssl_full.a and /dev/null differ diff --git a/usockets/lib/libuv.dll.a b/usockets/lib/libuv.dll.a deleted file mode 100644 index 9b65e61..0000000 Binary files a/usockets/lib/libuv.dll.a and /dev/null differ diff --git a/usockets/lib/libusockets_full.a b/usockets/lib/windows/libusockets_full.a similarity index 87% rename from usockets/lib/libusockets_full.a rename to usockets/lib/windows/libusockets_full.a index 59db778..c0fdf24 100644 Binary files a/usockets/lib/libusockets_full.a and b/usockets/lib/windows/libusockets_full.a differ diff --git a/usockets/lib/libuv.a b/usockets/lib/windows/libuv.a similarity index 100% rename from usockets/lib/libuv.a rename to usockets/lib/windows/libuv.a diff --git a/usockets/usockets.v b/usockets/usockets.v index 2ea4486..85c2a45 100644 --- a/usockets/usockets.v +++ b/usockets/usockets.v @@ -2,41 +2,36 @@ module usockets // 条件编译:根据操作系统选择正确的路径和库 // @VMODROOT 指向包含 v.mod 的模块根目录 (v-hono/) +// 预编译库按平台存放在 usockets/lib/{platform}/ 目录 $if windows { #flag -DLIBUS_USE_LIBUV #flag -DLIBUS_NO_SSL #flag -I@VMODROOT/usockets/include - #flag -L@VMODROOT/usockets/lib - #flag @VMODROOT/usockets/lib/libusockets_full.a - #flag -lws2_32 -liphlpapi -lpsapi -luserenv -lole32 + #flag -L@VMODROOT/usockets/lib/windows + #flag @VMODROOT/usockets/lib/windows/libusockets_full.a + #flag -lws2_32 -liphlpapi -lpsapi -luserenv -lole32 -ldbghelp } $else $if macos { - // macOS: 支持 Apple Silicon (M1/M2/M3) 和 Intel Mac #flag -DLIBUS_USE_LIBUV #flag -DLIBUS_NO_SSL - - // libuv 路径 - 根据架构选择 Homebrew 路径 - $if arm64 { - #flag -I/opt/homebrew/include - #flag -L/opt/homebrew/lib - } $else { - #flag -I/usr/local/include - #flag -L/usr/local/lib - } - - // uSockets 库路径 #flag -I@VMODROOT/usockets/include - #flag -L@VMODROOT/usockets/lib - #flag @VMODROOT/usockets/lib/libusockets_full.a - #flag -luv + + $if arm64 { + // Apple Silicon (M1/M2/M3) + #flag -L@VMODROOT/usockets/lib/macos-arm64 + #flag @VMODROOT/usockets/lib/macos-arm64/libusockets_full.a + } $else { + // Intel Mac + #flag -L@VMODROOT/usockets/lib/macos-x64 + #flag @VMODROOT/usockets/lib/macos-x64/libusockets_full.a + } } $else { // Linux 和其他平台 #flag -DLIBUS_USE_LIBUV #flag -DLIBUS_NO_SSL #flag -I@VMODROOT/usockets/include - #flag -L@VMODROOT/usockets/lib - #flag @VMODROOT/usockets/lib/libusockets_full.a - #flag -luv + #flag -L@VMODROOT/usockets/lib/linux + #flag @VMODROOT/usockets/lib/linux/libusockets_full.a } #include "libusockets.h" @@ -105,8 +100,6 @@ pub fn (ctx SocketContext) on_writable(h voidptr) { C.us_socket_context_on_writa pub fn (ctx SocketContext) on_timeout(h voidptr) { C.us_socket_context_on_timeout(0, ctx, h) } pub fn (ctx SocketContext) on_end(h voidptr) { C.us_socket_context_on_end(0, ctx, h) } pub fn (ctx SocketContext) listen(port int) ListenSocket { - // 参数: ssl=0, context, host=nil, port, options=LIBUS_LISTEN_DEFAULT(0), socket_ext_size=0 - // 注意: backlog 是在 uSockets 库内部硬编码的,不通过此函数传递 return C.us_socket_context_listen(0, ctx, unsafe { nil }, port, 0, 0) }