perf: 优化插件系统性能,消除重复实例化问题

- 添加plugins.Exists()函数,避免不必要的插件实例创建
- 合并PluginInfo数据结构,统一插件工厂和端口信息存储
- 修复Scanner中重复调用plugins.Get()的性能问题
- 优化BaseScanStrategy.pluginExists()实现效率

主要性能改进:
* 消除21×57=1197次不必要的本地插件实例化
* 提升插件存在性检查效率,从O(n)遍历优化为O(1)查找
* 改善数据内聚性,插件元数据集中管理
* 保持所有现有插件控制逻辑和功能完整性

测试验证:
* 无-local参数时不再创建本地插件实例
* 端口匹配、Web检测、互斥验证等功能正常
* 插件注册和执行逻辑保持向后兼容
This commit is contained in:
ZacharyZcR 2025-08-26 19:53:57 +08:00
parent 43ddb3630d
commit d981f0100f
3 changed files with 31 additions and 21 deletions

View File

@ -122,14 +122,8 @@ func (b *BaseScanStrategy) IsPluginApplicableByName(pluginName string, targetHos
// pluginExists 检查插件是否存在,不创建实例 // pluginExists 检查插件是否存在,不创建实例
func (b *BaseScanStrategy) pluginExists(pluginName string) bool { func (b *BaseScanStrategy) pluginExists(pluginName string) bool {
// 使用All()获取所有注册插件名称避免调用Get()创建实例 // 使用统一插件系统的Exists方法避免创建实例和遍历
allPlugins := plugins.All() return plugins.Exists(pluginName)
for _, name := range allPlugins {
if name == pluginName {
return true
}
}
return false
} }
// getPluginPorts 获取插件端口列表 // getPluginPorts 获取插件端口列表

View File

@ -122,7 +122,8 @@ func ExecuteScanTasks(targets []common.HostInfo, strategy ScanStrategy, ch *chan
} }
for _, pluginName := range pluginsToRun { for _, pluginName := range pluginsToRun {
if plugins.Get(pluginName) == nil { // 使用Exists检查避免不必要的插件实例创建
if !plugins.Exists(pluginName) {
continue continue
} }
@ -144,7 +145,8 @@ func countApplicableTasks(targets []common.HostInfo, pluginsToRun []string, isCu
} }
for _, pluginName := range pluginsToRun { for _, pluginName := range pluginsToRun {
if plugins.Get(pluginName) != nil && // 使用Exists检查避免不必要的插件实例创建
if plugins.Exists(pluginName) &&
strategy.IsPluginApplicableByName(pluginName, target.Host, targetPort, isCustomMode) { strategy.IsPluginApplicableByName(pluginName, target.Host, targetPort, isCustomMode) {
count++ count++
} }

View File

@ -55,26 +55,31 @@ type Credential struct {
KeyData []byte KeyData []byte
} }
// PluginInfo 插件信息结构 - 合并工厂和端口信息
type PluginInfo struct {
factory func() Plugin
ports []int
}
// 全局插件注册表 - 一个数据结构解决所有问题 // 全局插件注册表 - 一个数据结构解决所有问题
var ( var (
plugins = make(map[string]func() Plugin) plugins = make(map[string]*PluginInfo)
pluginPorts = make(map[string][]int) // 存储插件端口信息
mutex sync.RWMutex mutex sync.RWMutex
) )
// Register 注册插件 - 一个函数统治所有注册 // Register 注册插件 - 一个函数统治所有注册
func Register(name string, factory func() Plugin) { func Register(name string, factory func() Plugin) {
mutex.Lock() RegisterWithPorts(name, factory, []int{})
defer mutex.Unlock()
plugins[name] = factory
} }
// RegisterWithPorts 注册带端口信息的插件 // RegisterWithPorts 注册带端口信息的插件
func RegisterWithPorts(name string, factory func() Plugin, ports []int) { func RegisterWithPorts(name string, factory func() Plugin, ports []int) {
mutex.Lock() mutex.Lock()
defer mutex.Unlock() defer mutex.Unlock()
plugins[name] = factory plugins[name] = &PluginInfo{
pluginPorts[name] = ports factory: factory,
ports: ports,
}
} }
// Get 获取插件实例 // Get 获取插件实例
@ -82,8 +87,8 @@ func Get(name string) Plugin {
mutex.RLock() mutex.RLock()
defer mutex.RUnlock() defer mutex.RUnlock()
if factory, exists := plugins[name]; exists { if info, exists := plugins[name]; exists {
return factory() return info.factory()
} }
return nil return nil
} }
@ -100,13 +105,22 @@ func All() []string {
return names return names
} }
// Exists 检查插件是否存在,不创建实例 - 解决性能问题
func Exists(name string) bool {
mutex.RLock()
defer mutex.RUnlock()
_, exists := plugins[name]
return exists
}
// GetPluginPorts 获取插件端口列表 // GetPluginPorts 获取插件端口列表
func GetPluginPorts(name string) []int { func GetPluginPorts(name string) []int {
mutex.RLock() mutex.RLock()
defer mutex.RUnlock() defer mutex.RUnlock()
if ports, exists := pluginPorts[name]; exists { if info, exists := plugins[name]; exists {
return ports return info.ports
} }
return []int{} // 返回空列表表示适用于所有端口 return []int{} // 返回空列表表示适用于所有端口
} }