mirror of
https://github.com/Syngnat/GoNavi.git
synced 2026-06-23 06:53:52 +08:00
- GC 策略:主进程与 driver-agent 启动时收紧 SetGCPercent 至 50 - 周期回收:scan_rows 与 callStreamQuery 每 5 万行触发 runtime.GC - 自适应限流:driver-agent 引入 GOMEMLIMIT 自适应策略,2GB 起步按 1GB 步长抬升至 8GB 上限 - 批次调优:流式批次由 256 行缩减至 64 行,降低 JSON 编解码瞬时峰值
142 lines
3.8 KiB
Go
142 lines
3.8 KiB
Go
package main
|
||
|
||
import (
|
||
"context"
|
||
"fmt"
|
||
"os"
|
||
"runtime/debug"
|
||
"strings"
|
||
|
||
aiservice "GoNavi-Wails/internal/ai/service"
|
||
"GoNavi-Wails/internal/app"
|
||
"GoNavi-Wails/internal/logger"
|
||
"GoNavi-Wails/internal/mcpserver"
|
||
|
||
"github.com/wailsapp/wails/v2"
|
||
"github.com/wailsapp/wails/v2/pkg/options"
|
||
"github.com/wailsapp/wails/v2/pkg/options/assetserver"
|
||
"github.com/wailsapp/wails/v2/pkg/options/mac"
|
||
"github.com/wailsapp/wails/v2/pkg/options/windows"
|
||
)
|
||
|
||
func main() {
|
||
// 大结果集导出(88W+ 行)时,JSON 编解码会产生 5-8 倍内存副本,
|
||
// Go 默认 GOGC=100 下堆翻倍才触发 GC,叠加 Windows MADV_FREE 不归还 RSS,
|
||
// 会导致 RSS 单调爬升到峰值后不下降。这里收紧到 50,让 GC 更早触发。
|
||
// 代价是 CPU 开销略增,但导出/导入场景属 I/O 密集型,GC 开销可忽略。
|
||
debug.SetGCPercent(50)
|
||
|
||
if runSpecialMode(os.Args[1:]) {
|
||
return
|
||
}
|
||
|
||
// Create an instance of the app structure
|
||
application := app.NewApp()
|
||
aiService := aiservice.NewService()
|
||
lowMemoryMode := isLowMemoryMode()
|
||
backgroundColour := &options.RGBA{R: 0, G: 0, B: 0, A: 0}
|
||
windowsBackdrop := windows.Acrylic
|
||
if lowMemoryMode {
|
||
backgroundColour = &options.RGBA{R: 255, G: 255, B: 255, A: 255}
|
||
windowsBackdrop = windows.None
|
||
}
|
||
|
||
// Create application with options
|
||
err := wails.Run(&options.App{
|
||
Title: "GoNavi",
|
||
Width: 1024,
|
||
Height: 768,
|
||
MinWidth: 900,
|
||
MinHeight: 600,
|
||
Frameless: true,
|
||
AssetServer: &assetserver.Options{
|
||
Assets: assets,
|
||
},
|
||
BackgroundColour: backgroundColour,
|
||
OnStartup: func(ctx context.Context) {
|
||
app.InitializeLifecycle(application, ctx)
|
||
aiservice.InitializeLifecycle(aiService, ctx)
|
||
},
|
||
OnShutdown: func(ctx context.Context) {
|
||
aiService.Shutdown()
|
||
application.Shutdown()
|
||
},
|
||
Bind: []interface{}{
|
||
application,
|
||
aiService,
|
||
},
|
||
Windows: &windows.Options{
|
||
WebviewIsTransparent: !lowMemoryMode,
|
||
WindowIsTranslucent: !lowMemoryMode,
|
||
BackdropType: windowsBackdrop,
|
||
DisableWindowIcon: false,
|
||
DisableFramelessWindowDecorations: false,
|
||
WebviewUserDataPath: resolveWindowsWebviewUserDataPath(),
|
||
},
|
||
Mac: &mac.Options{
|
||
WebviewIsTransparent: true,
|
||
WindowIsTranslucent: true,
|
||
},
|
||
})
|
||
|
||
if err != nil {
|
||
logger.Error(err, "应用启动失败")
|
||
}
|
||
}
|
||
|
||
func runSpecialMode(args []string) bool {
|
||
if !shouldRunMCPServerMode(args) {
|
||
return false
|
||
}
|
||
|
||
if err := runMCPServerMode(context.Background(), args[1:]); err != nil {
|
||
logger.Error(err, "GoNavi MCP Server 退出")
|
||
}
|
||
return true
|
||
}
|
||
|
||
func runMCPServerMode(ctx context.Context, args []string) error {
|
||
if len(args) == 0 {
|
||
return mcpserver.RunAppStdioServer(ctx)
|
||
}
|
||
|
||
mode := strings.ToLower(strings.TrimSpace(args[0]))
|
||
switch mode {
|
||
case "stdio", "--stdio":
|
||
return mcpserver.RunAppStdioServer(ctx)
|
||
case "http", "--http", "streamable-http", "--streamable-http":
|
||
options, err := mcpserver.ParseHTTPServerOptions(args[1:])
|
||
if err != nil {
|
||
return err
|
||
}
|
||
logger.Infof("GoNavi MCP Streamable HTTP Server 启动:addr=%s path=%s schemaOnly=%v", options.Addr, options.Path, options.SchemaOnly)
|
||
return mcpserver.RunAppStreamableHTTPServer(ctx, options)
|
||
case "remote-config", "--remote-config":
|
||
return mcpserver.WriteRemoteMCPClientConfig(os.Stdout, args[1:])
|
||
default:
|
||
return fmt.Errorf("未知 MCP server 模式: %s(支持 stdio/http/remote-config)", args[0])
|
||
}
|
||
}
|
||
|
||
func shouldRunMCPServerMode(args []string) bool {
|
||
if len(args) == 0 {
|
||
return false
|
||
}
|
||
|
||
switch strings.ToLower(strings.TrimSpace(args[0])) {
|
||
case "mcp-server", "--mcp-server":
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|
||
|
||
func isLowMemoryMode() bool {
|
||
switch strings.ToLower(strings.TrimSpace(os.Getenv("GONAVI_LOW_MEMORY_MODE"))) {
|
||
case "1", "true", "yes", "on":
|
||
return true
|
||
default:
|
||
return false
|
||
}
|
||
}
|