Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e8dd4548 | ||
|
|
a702746df7 | ||
|
|
a57ce2e77a | ||
|
|
7a08c3142a | ||
|
|
362015c1cf | ||
|
|
0969901481 | ||
|
|
6bddfc3731 | ||
|
|
26ac804b1d | ||
|
|
56299b5485 | ||
|
|
d31492fd59 | ||
|
|
e19f799e46 |
@@ -2,7 +2,6 @@
|
|||||||
*.exe
|
*.exe
|
||||||
*.out
|
*.out
|
||||||
*.o
|
*.o
|
||||||
*.a
|
|
||||||
*.so
|
*.so
|
||||||
*.dll
|
*.dll
|
||||||
|
|
||||||
|
|||||||
@@ -50,8 +50,13 @@ cd v-hono
|
|||||||
### Standard Build (picoev backend)
|
### Standard Build (picoev backend)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
v your_app.v -o app.exe
|
# macOS / Linux
|
||||||
./app.exe
|
v -prod -o app your_app.v
|
||||||
|
./app
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
v -o app.exe your_app.v
|
||||||
|
.\app.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
### High-Performance Build (uSockets backend)
|
### High-Performance Build (uSockets backend)
|
||||||
@@ -59,25 +64,33 @@ v your_app.v -o app.exe
|
|||||||
For maximum performance with uSockets backend:
|
For maximum performance with uSockets backend:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
v -enable-globals -cc gcc -ldflags "-ldbghelp" your_app.v -o app.exe
|
# macOS / Linux
|
||||||
./app.exe
|
v -enable-globals -prod -o app your_app.v
|
||||||
|
./app
|
||||||
|
|
||||||
|
# Windows (must use gcc, tcc does not support .a static library format)
|
||||||
|
v -enable-globals -cc gcc -ldflags "-ldbghelp" -o app.exe your_app.v
|
||||||
|
.\app.exe
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note**: The `-enable-globals` flag is required for uSockets backend. The `-ldflags "-ldbghelp"` fixes Windows linking issues.
|
**Important Notes:**
|
||||||
|
- The `-enable-globals` flag is required for uSockets backend
|
||||||
|
- On Windows, you **must** use `-cc gcc` because V's default compiler (tcc) does not support MinGW `.a` static library format
|
||||||
|
- The `-ldflags "-ldbghelp"` is required on Windows for libuv linking
|
||||||
|
|
||||||
#### Windows Prerequisites
|
#### Windows Prerequisites
|
||||||
|
|
||||||
To use uSockets backend on Windows, you need:
|
To use uSockets backend on Windows, you need:
|
||||||
|
|
||||||
1. **GCC (MinGW-w64)** - C compiler
|
1. **GCC (MinGW-w64)** - C compiler (required, tcc is not supported)
|
||||||
```powershell
|
```powershell
|
||||||
# Install via Scoop
|
# Install via Scoop (recommended)
|
||||||
scoop install mingw
|
scoop install mingw
|
||||||
|
|
||||||
# Or via Chocolatey
|
# Or via Chocolatey
|
||||||
choco install mingw
|
choco install mingw
|
||||||
|
|
||||||
# Or download from: https://www.mingw-w64.org/downloads/
|
# Or download w64devkit from: https://github.com/skeeto/w64devkit/releases
|
||||||
```
|
```
|
||||||
|
|
||||||
2. **V Compiler** - Version 0.4.x or later
|
2. **V Compiler** - Version 0.4.x or later
|
||||||
@@ -94,7 +107,11 @@ To use uSockets backend on Windows, you need:
|
|||||||
v version # Should show V 0.4.x
|
v version # Should show V 0.4.x
|
||||||
```
|
```
|
||||||
|
|
||||||
The uSockets library and libuv are pre-compiled and included in the `usockets/lib/` directory.
|
The uSockets library and libuv are pre-compiled and included in the `usockets/lib/{platform}/` directory:
|
||||||
|
- `usockets/lib/windows/` - Windows x64
|
||||||
|
- `usockets/lib/linux/` - Linux x64
|
||||||
|
- `usockets/lib/macos-arm64/` - macOS Apple Silicon
|
||||||
|
- `usockets/lib/macos-x64/` - macOS Intel
|
||||||
|
|
||||||
### Using uSockets Backend
|
### Using uSockets Backend
|
||||||
|
|
||||||
|
|||||||
@@ -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{
|
||||||
if err != nil {
|
MaxIdleConns: concurrency,
|
||||||
continue
|
MaxIdleConnsPerHost: concurrency,
|
||||||
}
|
IdleConnTimeout: 30 * time.Second,
|
||||||
io.Copy(io.Discard, resp.Body)
|
DisableKeepAlives: false,
|
||||||
resp.Body.Close()
|
}
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
success++
|
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()
|
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
|
||||||
}
|
}
|
||||||
|
|||||||
+94
-27
@@ -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
|
||||||
echo "编译 uSockets..."
|
compile_libuv() {
|
||||||
cd "$USOCKETS_DIR"
|
echo "编译 libuv..."
|
||||||
make clean
|
cd "$LIBUV_DIR"
|
||||||
|
rm -rf build 2>/dev/null || true
|
||||||
# 根据系统选择编译参数
|
mkdir -p build
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
cd build
|
||||||
# macOS
|
|
||||||
if [[ $(uname -m) == "arm64" ]]; then
|
if ! command -v cmake &> /dev/null; then
|
||||||
# Apple Silicon
|
echo "错误: 需要安装 cmake"
|
||||||
WITH_LIBUV=1 CFLAGS="-I/opt/homebrew/include" make
|
echo " macOS: brew install cmake"
|
||||||
else
|
echo " Linux: sudo apt install cmake 或 sudo yum install cmake"
|
||||||
# Intel Mac
|
echo " Windows: scoop install cmake 或 choco install cmake"
|
||||||
WITH_LIBUV=1 CFLAGS="-I/usr/local/include" make
|
exit 1
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
# Linux
|
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "mingw"* ]]; then
|
||||||
WITH_LIBUV=1 make
|
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||||
fi
|
else
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||||
|
fi
|
||||||
|
|
||||||
|
cmake --build . --config Release
|
||||||
|
}
|
||||||
|
|
||||||
# 复制到 v-hono
|
# 编译 uSockets
|
||||||
echo "复制库文件..."
|
compile_usockets() {
|
||||||
cp "$USOCKETS_DIR/uSockets.a" "$SCRIPT_DIR/../lib/libusockets_full.a"
|
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 ""
|
||||||
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.
+16
-23
@@ -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,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.1'
|
version: '0.7.6'
|
||||||
license: 'MIT'
|
license: 'MIT'
|
||||||
dependencies: []
|
dependencies: []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user