fix: resolve AsyncLocalStorage + dir issues in custom server, update benchmark script
Co-authored-by: ajnart <49837342+ajnart@users.noreply.github.com>
This commit is contained in:
1 parent
c8ae7f283a
commit
8994bdedc3
3 files changed
+120
-80
No files matched your search
@@ -5,7 +5,7 @@
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "pnpm with-env next build && pnpm build:custom-server",
|
||||
"build:custom-server": "esbuild server.ts --bundle --platform=node --outfile=customServer.cjs --external:bcrypt --external:@opentelemetry/api --external:deasync --external:cpu-features --loader:.html=text --loader:.scss=text --loader:.node=text",
|
||||
"build:custom-server": "esbuild server.ts --bundle --platform=node --outfile=customServer.cjs --external:next --external:bcrypt --external:@opentelemetry/api --external:deasync --external:cpu-features --loader:.html=text --loader:.scss=text --loader:.node=text",
|
||||
"clean": "git clean -xdf .next .turbo node_modules",
|
||||
"dev": "pnpm with-env tsx ./server.ts",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
// Must be imported first to set up globalThis.AsyncLocalStorage for Next.js
|
||||
import "next/dist/server/node-environment-baseline";
|
||||
|
||||
import { createServer } from "http";
|
||||
import path from "path";
|
||||
import next from "next";
|
||||
import { parse } from "url";
|
||||
import { applyWSSHandler } from "@trpc/server/adapters/ws";
|
||||
@@ -15,8 +19,10 @@ const logger = createLogger({ module: "customServer" });
|
||||
const dev = process.env.NODE_ENV !== "production";
|
||||
const hostname = process.env.HOSTNAME || "localhost";
|
||||
const port = parseInt(process.env.PORT || "3000", 10);
|
||||
// Resolve the directory of this file so Next.js can find the app/pages dirs
|
||||
const dir = path.resolve(__dirname);
|
||||
|
||||
const app = next({ dev, hostname, port });
|
||||
const app = next({ dev, hostname, port, dir });
|
||||
const handle = app.getRequestHandler();
|
||||
|
||||
app.prepare().then(() => {
|
||||
|
||||
+112
-78
@@ -1,114 +1,148 @@
|
||||
#!/usr/bin/env bash
|
||||
# Benchmark memory usage of the WebSocket server approach
|
||||
# Usage: ./scripts/benchmark-memory.sh [approach]
|
||||
# approach: "separate" (current: separate ws server) or "integrated" (custom Next.js server)
|
||||
# Benchmark memory usage: separate ws server vs integrated custom Next.js server
|
||||
# Usage: ./scripts/benchmark-memory.sh [approach] [wait_seconds]
|
||||
# approach: "separate" | "integrated" | "both" (default: both)
|
||||
|
||||
set -e
|
||||
|
||||
APPROACH="${1:-separate}"
|
||||
WAIT_SECONDS="${2:-10}"
|
||||
APPROACH="${1:-both}"
|
||||
WAIT_SECONDS="${2:-15}"
|
||||
|
||||
echo "============================================"
|
||||
echo "Memory Benchmark: $APPROACH approach"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
measure_memory() {
|
||||
local pid=$1
|
||||
measure_process_tree_memory() {
|
||||
local root_pid=$1
|
||||
local label=$2
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
local rss
|
||||
rss=$(ps -o rss= -p "$pid" 2>/dev/null | tr -d ' ')
|
||||
if [ -n "$rss" ]; then
|
||||
local rss_mb
|
||||
rss_mb=$(echo "scale=2; $rss / 1024" | bc)
|
||||
echo "$label (PID $pid): ${rss_mb} MB (RSS: ${rss} KB)"
|
||||
echo "$rss"
|
||||
else
|
||||
echo "$label (PID $pid): unable to read memory"
|
||||
echo "0"
|
||||
fi
|
||||
else
|
||||
local total_rss=0
|
||||
|
||||
if [ -z "$root_pid" ] || ! kill -0 "$root_pid" 2>/dev/null; then
|
||||
echo "$label: not running"
|
||||
echo "0"
|
||||
return
|
||||
fi
|
||||
|
||||
# Measure root process
|
||||
local root_rss
|
||||
root_rss=$(grep VmRSS /proc/$root_pid/status 2>/dev/null | awk '{print $2}')
|
||||
root_rss=${root_rss:-0}
|
||||
total_rss=$root_rss
|
||||
local root_mb
|
||||
root_mb=$(echo "scale=2; $root_rss / 1024" | bc)
|
||||
echo " $label (PID $root_pid): ${root_mb} MB"
|
||||
|
||||
# Measure child processes recursively
|
||||
for cpid in $(pgrep -P "$root_pid" 2>/dev/null); do
|
||||
if kill -0 "$cpid" 2>/dev/null; then
|
||||
local child_rss
|
||||
child_rss=$(grep VmRSS /proc/$cpid/status 2>/dev/null | awk '{print $2}')
|
||||
child_rss=${child_rss:-0}
|
||||
total_rss=$((total_rss + child_rss))
|
||||
local child_mb
|
||||
child_mb=$(echo "scale=2; $child_rss / 1024" | bc)
|
||||
local child_cmd
|
||||
child_cmd=$(cat /proc/$cpid/cmdline 2>/dev/null | tr '\0' ' ' | head -c 60)
|
||||
echo " Child (PID $cpid): ${child_mb} MB - $child_cmd"
|
||||
|
||||
# Grandchildren
|
||||
for gpid in $(pgrep -P "$cpid" 2>/dev/null); do
|
||||
if kill -0 "$gpid" 2>/dev/null; then
|
||||
local gchild_rss
|
||||
gchild_rss=$(grep VmRSS /proc/$gpid/status 2>/dev/null | awk '{print $2}')
|
||||
gchild_rss=${gchild_rss:-0}
|
||||
total_rss=$((total_rss + gchild_rss))
|
||||
local gchild_mb
|
||||
gchild_mb=$(echo "scale=2; $gchild_rss / 1024" | bc)
|
||||
local gchild_cmd
|
||||
gchild_cmd=$(cat /proc/$gpid/cmdline 2>/dev/null | tr '\0' ' ' | head -c 60)
|
||||
echo " Grandchild (PID $gpid): ${gchild_mb} MB - $gchild_cmd"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
done
|
||||
|
||||
local total_mb
|
||||
total_mb=$(echo "scale=2; $total_rss / 1024" | bc)
|
||||
echo " Subtotal: ${total_mb} MB"
|
||||
# Export for caller
|
||||
eval "${label}_TOTAL_RSS=$total_rss"
|
||||
}
|
||||
|
||||
cleanup() {
|
||||
echo ""
|
||||
echo "Cleaning up processes..."
|
||||
for pid in "${PIDS[@]}"; do
|
||||
cleanup_pids() {
|
||||
for pid in "$@"; do
|
||||
if [ -n "$pid" ] && kill -0 "$pid" 2>/dev/null; then
|
||||
kill "$pid" 2>/dev/null || true
|
||||
fi
|
||||
done
|
||||
wait 2>/dev/null || true
|
||||
echo "Done."
|
||||
}
|
||||
|
||||
trap cleanup EXIT
|
||||
run_separate() {
|
||||
echo "============================================"
|
||||
echo "SEPARATE APPROACH (Current: WS + Next.js)"
|
||||
echo "============================================"
|
||||
|
||||
PIDS=()
|
||||
TOTAL_RSS=0
|
||||
|
||||
if [ "$APPROACH" = "separate" ]; then
|
||||
echo "Starting separate WebSocket server (current approach)..."
|
||||
echo "---"
|
||||
|
||||
# Start the WebSocket server
|
||||
# Start WS server
|
||||
node apps/websocket/wssServer.cjs &
|
||||
WSS_PID=$!
|
||||
PIDS+=("$WSS_PID")
|
||||
WS_PID=$!
|
||||
sleep 5
|
||||
|
||||
# Start the Next.js server
|
||||
node apps/nextjs/server.js &
|
||||
NEXTJS_PID=$!
|
||||
PIDS+=("$NEXTJS_PID")
|
||||
WS_LISTEN_PID=$(lsof -i :3001 -t 2>/dev/null | head -1)
|
||||
echo "WS server listening PID: $WS_LISTEN_PID"
|
||||
|
||||
echo "Waiting ${WAIT_SECONDS}s for processes to stabilize..."
|
||||
sleep "$WAIT_SECONDS"
|
||||
WS_RSS=$(grep VmRSS /proc/${WS_LISTEN_PID}/status 2>/dev/null | awk '{print $2}')
|
||||
WS_RSS=${WS_RSS:-0}
|
||||
WS_MB=$(echo "scale=2; $WS_RSS / 1024" | bc)
|
||||
echo " WebSocket Server: ${WS_MB} MB"
|
||||
|
||||
echo ""
|
||||
echo "--- Memory Usage (Separate Approach) ---"
|
||||
wss_mem=$(measure_memory "$WSS_PID" "WebSocket Server" | tail -1)
|
||||
nextjs_mem=$(measure_memory "$NEXTJS_PID" "Next.js Server" | tail -1)
|
||||
echo "TOTAL (Separate WS only): ${WS_MB} MB"
|
||||
echo "Note: Next.js dev server not included (would add ~1.5-2.5 GB)"
|
||||
echo "============================================"
|
||||
|
||||
TOTAL_RSS=$((wss_mem + nextjs_mem))
|
||||
TOTAL_MB=$(echo "scale=2; $TOTAL_RSS / 1024" | bc)
|
||||
cleanup_pids "$WS_PID"
|
||||
SEPARATE_RSS=$WS_RSS
|
||||
}
|
||||
|
||||
echo ""
|
||||
echo "TOTAL: ${TOTAL_MB} MB (RSS: ${TOTAL_RSS} KB)"
|
||||
run_integrated() {
|
||||
echo "============================================"
|
||||
echo "INTEGRATED APPROACH (Custom Next.js Server)"
|
||||
echo "============================================"
|
||||
|
||||
elif [ "$APPROACH" = "integrated" ]; then
|
||||
echo "Starting integrated custom Next.js server (new approach)..."
|
||||
echo "---"
|
||||
|
||||
# Start the custom server (Next.js + WebSocket integrated)
|
||||
node apps/nextjs/customServer.cjs &
|
||||
cd apps/nextjs
|
||||
node customServer.cjs &
|
||||
CUSTOM_PID=$!
|
||||
PIDS+=("$CUSTOM_PID")
|
||||
cd ../..
|
||||
|
||||
echo "Waiting ${WAIT_SECONDS}s for process to stabilize..."
|
||||
echo "Waiting ${WAIT_SECONDS}s for server to stabilize..."
|
||||
sleep "$WAIT_SECONDS"
|
||||
|
||||
measure_process_tree_memory "$CUSTOM_PID" "CustomServer"
|
||||
echo ""
|
||||
echo "--- Memory Usage (Integrated Approach) ---"
|
||||
custom_mem=$(measure_memory "$CUSTOM_PID" "Custom Server (Next.js + WS)" | tail -1)
|
||||
INTEGRATED_RSS=${CustomServer_TOTAL_RSS:-0}
|
||||
INTEGRATED_MB=$(echo "scale=2; $INTEGRATED_RSS / 1024" | bc)
|
||||
echo "TOTAL (Integrated): ${INTEGRATED_MB} MB"
|
||||
echo "============================================"
|
||||
|
||||
TOTAL_RSS=$custom_mem
|
||||
TOTAL_MB=$(echo "scale=2; $TOTAL_RSS / 1024" | bc)
|
||||
cleanup_pids "$CUSTOM_PID"
|
||||
}
|
||||
|
||||
if [ "$APPROACH" = "separate" ] || [ "$APPROACH" = "both" ]; then
|
||||
run_separate
|
||||
echo ""
|
||||
echo "TOTAL: ${TOTAL_MB} MB (RSS: ${TOTAL_RSS} KB)"
|
||||
|
||||
else
|
||||
echo "Unknown approach: $APPROACH"
|
||||
echo "Usage: $0 [separate|integrated] [wait_seconds]"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Benchmark complete for: $APPROACH"
|
||||
echo "Total memory: ${TOTAL_MB} MB"
|
||||
echo "============================================"
|
||||
if [ "$APPROACH" = "integrated" ] || [ "$APPROACH" = "both" ]; then
|
||||
# Clean up lock from previous run
|
||||
rm -rf apps/nextjs/.next/dev/lock
|
||||
run_integrated
|
||||
echo ""
|
||||
fi
|
||||
|
||||
if [ "$APPROACH" = "both" ]; then
|
||||
echo "============================================"
|
||||
echo "COMPARISON"
|
||||
echo "============================================"
|
||||
SEP_MB=$(echo "scale=2; ${SEPARATE_RSS:-0} / 1024" | bc)
|
||||
INT_MB=$(echo "scale=2; ${INTEGRATED_RSS:-0} / 1024" | bc)
|
||||
echo "Separate WS server only: ${SEP_MB} MB"
|
||||
echo "Integrated custom server: ${INT_MB} MB"
|
||||
echo "(The integrated server includes both Next.js AND WebSocket)"
|
||||
echo "============================================"
|
||||
fi
|
||||
Reference in new issue
Block a user