This commit is contained in:
unknown
2026-02-04 20:27:13 +08:00
commit 3b042d1dad
9410 changed files with 1488147 additions and 0 deletions

View File

@@ -0,0 +1,161 @@
// Copyright 2021 Liuxiangchao iwind.liu@gmail.com. All rights reserved.
//go:build script
// +build script
package js
import (
"github.com/TeaOSLab/EdgeNode/internal/remotelogs"
"github.com/TeaOSLab/EdgeNode/internal/utils/goman"
memutils "github.com/TeaOSLab/EdgeNode/internal/utils/mem"
"github.com/iwind/TeaGo/Tea"
"time"
)
type IsolatePool struct {
hotIsolates []*Isolate // 当前正在使用的isolates
coldIsolates []*Isolate // 等待回收的isolates
coldTicker *time.Ticker
coldIndex int
maxSize int
index int
}
func NewIsolatePool(maxSize int) (*IsolatePool, error) {
if maxSize <= 0 {
maxSize = 1
}
if maxSize > 512 {
maxSize = 512
}
var pool = &IsolatePool{
hotIsolates: make([]*Isolate, maxSize),
maxSize: maxSize,
}
err := pool.init()
if err != nil {
remotelogs.Error("SCRIPT", "create isolate pool failed: "+err.Error())
pool.Dispose()
return nil, err
}
return pool, nil
}
func NewAutoIsolatePool() (*IsolatePool, error) {
// 每 512M 内存一个isolate
var totalMemory = memutils.SystemMemoryGB()
var count = totalMemory * 2
if count <= 0 {
count = 2
}
// 防止在有些系统上OOM
if count > 256 {
count = 256
}
return NewIsolatePool(count)
}
func (this *IsolatePool) init() error {
for i := 0; i < this.maxSize; i++ {
isolate, err := NewIsolate()
if err != nil {
return err
}
this.hotIsolates[i] = isolate
}
// run init functions
if len(this.hotIsolates) > 0 {
var isolate = this.hotIsolates[0]
ctx, err := isolate.GetContext()
if err == nil {
_, err = ctx.Run("gojs.runOnce()", "utils.js")
if err != nil {
remotelogs.Error("SCRIPT", "run once functions failed: "+err.Error())
}
isolate.PutContext(ctx)
}
}
this.coldTicker = time.NewTicker(5 * time.Second)
if Tea.IsTesting() {
this.coldTicker = time.NewTicker(5 * time.Second)
}
goman.New(func() {
for range this.coldTicker.C {
this.tick()
}
})
return nil
}
func (this *IsolatePool) tick() {
// dispose cold isolates
if len(this.coldIsolates) > 0 {
var newIndex = -1
for index, coldIsolate := range this.coldIsolates {
if coldIsolate.IsUsing() {
break
}
newIndex = index
coldIsolate.Dispose()
}
if newIndex >= 0 {
this.coldIsolates = this.coldIsolates[newIndex+1:]
}
}
// add new isolate
if this.coldIndex > this.maxSize-1 {
this.coldIndex = 0
}
var oldIsolate = this.hotIsolates[this.coldIndex]
if oldIsolate.OverUses() {
newIsolate, err := NewIsolate()
if err != nil {
remotelogs.Error("SCRIPT", "create isolate failed: "+err.Error())
return
}
this.hotIsolates[this.coldIndex] = newIsolate
this.coldIsolates = append(this.coldIsolates, oldIsolate)
}
this.coldIndex++
}
func (this *IsolatePool) GetContext() (*Context, error) {
this.index++ // 不需要加锁,这里没必要非常严格
var index = this.index
if index >= this.maxSize {
index = 0
this.index = 0
}
// TODO 未来实现循环查找可用的context防止因单个context执行时间过长阻塞整个isolate
return this.hotIsolates[index].GetContext()
}
func (this *IsolatePool) PutContext(ctx *Context) {
if ctx != nil {
ctx.Isolate().PutContext(ctx)
}
}
func (this *IsolatePool) MaxSize() int {
return this.maxSize
}
func (this *IsolatePool) Dispose() {
for _, isolate := range this.hotIsolates {
isolate.Dispose()
}
}