Compare commits

...
2 Commits
Author SHA1 Message Date
meiseayoung 26ac804b1d chore: update v.mod version 2026-01-05 11:07:41 +08:00
meiseayoung 56299b5485 refactor(usockets): reorganize lib directory structure for multi-platform support
- Organize lib directory by platform: windows/, macos-arm64/, macos-x64/, linux/
- Update build.sh to support unified build process for Windows/macOS/Linux
- Compile libuv + uSockets and merge into complete static library
- Update usockets.v conditional compilation to point to new directory structure
- Optimize benchmark tests with connection pooling for high concurrency testing
- Clean up unused legacy library files

Performance test results (Windows):
- 1000 concurrent, 1M requests: 35,223 req/s
- 10000 concurrent, 1M requests: 26,884 req/s
2026-01-05 11:06:56 +08:00
12 changed files with 151 additions and 63 deletions
+33 -5
View File
@@ -448,21 +448,49 @@ func checkKeepAlive(client *http.Client) bool {
func checkThroughput(client *http.Client) float64 { func checkThroughput(client *http.Client) float64 {
start := time.Now() start := time.Now()
success := 0 concurrency := 1000
requests := 200 totalRequests := 1000000
requestsPerWorker := totalRequests / concurrency
for i := 0; i < requests; i++ { // 创建共享的 Transport,启用连接池复用
resp, err := client.Get(baseURL + "/health") 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 { if err != nil {
continue continue
} }
io.Copy(io.Discard, resp.Body) io.Copy(io.Discard, resp.Body)
resp.Body.Close() resp.Body.Close()
if resp.StatusCode == 200 { if resp.StatusCode == 200 {
success++ localSuccess++
} }
} }
results <- localSuccess
}()
}
success := 0
for i := 0; i < concurrency; i++ {
success += <-results
}
elapsed := time.Since(start).Seconds() elapsed := time.Since(start).Seconds()
fmt.Printf("\n [并发: %d, 总请求: %d, 成功: %d, 耗时: %.2fs]\n ", concurrency, totalRequests, success, elapsed)
return float64(success) / elapsed return float64(success) / elapsed
} }
+92 -25
View File
@@ -1,13 +1,36 @@
#!/bin/bash #!/bin/bash
# uSockets 编译脚本 # 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 set -e
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
USOCKETS_DIR="/tmp/uSockets" USOCKETS_DIR="/tmp/uSockets"
LIBUV_DIR="/tmp/libuv"
MERGE_DIR="/tmp/merge_libs"
echo "=== uSockets 编译脚本 ===" 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 源码 # 检查是否有 uSockets 源码
if [ ! -d "$USOCKETS_DIR" ]; then 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" git clone --depth 1 https://github.com/uNetworking/uSockets.git "$USOCKETS_DIR"
fi 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 修改 # 应用 backlog 修改
echo "应用 backlog=16384 修改..." echo "应用 backlog=16384 修改..."
if [ -f "$SCRIPT_DIR/src/bsd.c" ]; then if [ -f "$SCRIPT_DIR/src/bsd.c" ]; then
cp "$SCRIPT_DIR/src/bsd.c" "$USOCKETS_DIR/src/bsd.c" cp "$SCRIPT_DIR/src/bsd.c" "$USOCKETS_DIR/src/bsd.c"
else else
# 如果没有本地修改的源码,直接修改
sed -i.bak 's/listen(listenFd, 512)/listen(listenFd, 16384)/g' "$USOCKETS_DIR/src/bsd.c" sed -i.bak 's/listen(listenFd, 512)/listen(listenFd, 16384)/g' "$USOCKETS_DIR/src/bsd.c"
fi fi
# 编译 # 编译 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
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
}
# 编译 uSockets
compile_usockets() {
echo "编译 uSockets..." echo "编译 uSockets..."
cd "$USOCKETS_DIR" cd "$USOCKETS_DIR"
make clean 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
if [[ "$OSTYPE" == "darwin"* ]]; then ar rcs uSockets.a *.o
# macOS rm -f *.o
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
fi
else
# Linux
WITH_LIBUV=1 make
fi
# 复制到 v-hono # 合并库文件
echo "复制库文件..." merge_libraries() {
cp "$USOCKETS_DIR/uSockets.a" "$SCRIPT_DIR/../lib/libusockets_full.a" echo "合并库文件..."
rm -rf "$MERGE_DIR"
mkdir -p "$MERGE_DIR"
echo "=== 编译完成 ===" cd "$MERGE_DIR"
echo "库文件: $SCRIPT_DIR/../lib/libusockets_full.a" 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 ""
echo "重新编译 v-hono 应用:" echo "=== 编译完成 ==="
echo " v -enable-globals -prod -o your_app your_app.v" 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
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+16 -23
View File
@@ -2,41 +2,36 @@ module usockets
// 条件编译:根据操作系统选择正确的路径和库 // 条件编译:根据操作系统选择正确的路径和库
// @VMODROOT 指向包含 v.mod 的模块根目录 (v-hono/) // @VMODROOT 指向包含 v.mod 的模块根目录 (v-hono/)
// 预编译库按平台存放在 usockets/lib/{platform}/ 目录
$if windows { $if windows {
#flag -DLIBUS_USE_LIBUV #flag -DLIBUS_USE_LIBUV
#flag -DLIBUS_NO_SSL #flag -DLIBUS_NO_SSL
#flag -I@VMODROOT/usockets/include #flag -I@VMODROOT/usockets/include
#flag -L@VMODROOT/usockets/lib #flag -L@VMODROOT/usockets/lib/windows
#flag @VMODROOT/usockets/lib/libusockets_full.a #flag @VMODROOT/usockets/lib/windows/libusockets_full.a
#flag -lws2_32 -liphlpapi -lpsapi -luserenv -lole32 #flag -lws2_32 -liphlpapi -lpsapi -luserenv -lole32 -ldbghelp
} $else $if macos { } $else $if macos {
// macOS: 支持 Apple Silicon (M1/M2/M3) 和 Intel Mac
#flag -DLIBUS_USE_LIBUV #flag -DLIBUS_USE_LIBUV
#flag -DLIBUS_NO_SSL #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 -I@VMODROOT/usockets/include
#flag -L@VMODROOT/usockets/lib
#flag @VMODROOT/usockets/lib/libusockets_full.a $if arm64 {
#flag -luv // 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 { } $else {
// Linux 和其他平台 // Linux 和其他平台
#flag -DLIBUS_USE_LIBUV #flag -DLIBUS_USE_LIBUV
#flag -DLIBUS_NO_SSL #flag -DLIBUS_NO_SSL
#flag -I@VMODROOT/usockets/include #flag -I@VMODROOT/usockets/include
#flag -L@VMODROOT/usockets/lib #flag -L@VMODROOT/usockets/lib/linux
#flag @VMODROOT/usockets/lib/libusockets_full.a #flag @VMODROOT/usockets/lib/linux/libusockets_full.a
#flag -luv
} }
#include "libusockets.h" #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_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) on_end(h voidptr) { C.us_socket_context_on_end(0, ctx, h) }
pub fn (ctx SocketContext) listen(port int) ListenSocket { 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) return C.us_socket_context_listen(0, ctx, unsafe { nil }, port, 0, 0)
} }
+1 -1
View File
@@ -1,7 +1,7 @@
Module { Module {
name: 'hono' name: 'hono'
description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.' description: 'A high-performance V language web framework inspired by Hono.js, featuring hybrid routing, LRU cache, middleware support, and more.'
version: '0.7.2' version: '0.7.3'
license: 'MIT' license: 'MIT'
dependencies: [] dependencies: []
} }