Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
22e8dd4548 | ||
|
|
a702746df7 | ||
|
|
a57ce2e77a | ||
|
|
7a08c3142a | ||
|
|
362015c1cf | ||
|
|
0969901481 | ||
|
|
6bddfc3731 | ||
|
|
26ac804b1d | ||
|
|
56299b5485 |
@@ -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
|
||||||
}
|
}
|
||||||
|
|||||||
+93
-26
@@ -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
|
||||||
|
cd build
|
||||||
|
|
||||||
# 根据系统选择编译参数
|
if ! command -v cmake &> /dev/null; then
|
||||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
echo "错误: 需要安装 cmake"
|
||||||
# macOS
|
echo " macOS: brew install cmake"
|
||||||
if [[ $(uname -m) == "arm64" ]]; then
|
echo " Linux: sudo apt install cmake 或 sudo yum install cmake"
|
||||||
# Apple Silicon
|
echo " Windows: scoop install cmake 或 choco install cmake"
|
||||||
WITH_LIBUV=1 CFLAGS="-I/opt/homebrew/include" make
|
exit 1
|
||||||
else
|
|
||||||
# Intel Mac
|
|
||||||
WITH_LIBUV=1 CFLAGS="-I/usr/local/include" make
|
|
||||||
fi
|
fi
|
||||||
else
|
|
||||||
# Linux
|
|
||||||
WITH_LIBUV=1 make
|
|
||||||
fi
|
|
||||||
|
|
||||||
# 复制到 v-hono
|
if [[ "$OSTYPE" == "msys" || "$OSTYPE" == "cygwin" || "$OSTYPE" == "mingw"* ]]; then
|
||||||
echo "复制库文件..."
|
cmake .. -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||||
cp "$USOCKETS_DIR/uSockets.a" "$SCRIPT_DIR/../lib/libusockets_full.a"
|
else
|
||||||
|
cmake .. -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF -DLIBUV_BUILD_SHARED=OFF
|
||||||
|
fi
|
||||||
|
|
||||||
echo "=== 编译完成 ==="
|
cmake --build . --config Release
|
||||||
echo "库文件: $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
|
||||||
|
}
|
||||||
|
|
||||||
|
# 合并库文件
|
||||||
|
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.
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.2'
|
version: '0.7.6'
|
||||||
license: 'MIT'
|
license: 'MIT'
|
||||||
dependencies: []
|
dependencies: []
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user