Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

大神,请教一个问题 #3

Open
Kline-x opened this issue Jun 5, 2020 · 7 comments
Open

大神,请教一个问题 #3

Kline-x opened this issue Jun 5, 2020 · 7 comments

Comments

@Kline-x
Copy link

Kline-x commented Jun 5, 2020

// 创建任务
task := &mortar.Task{
Handler: func(v ...interface{}) {
wg.Done()
fmt.Println(v)
},
}

for i := 0; i < 1000; i++ {
	wg.Add(1)
	// 添加任务函数的参数
	task.Params = []interface{}{i, i * 2, "hello"}
	// 将任务放入任务池
	pool.Put(task)
}

上面这段代码,因为task是指针,而且只在for上面初始化了一次,那是不是在for的时候每一次的task.Params就会覆盖上一次的值,导致Handler中得到的参数与想象中的不符?

@wazsmwazsm
Copy link
Owner

@914795561 你好,的确是这样的,这里的确是举例有点不严谨,应该在循环中创建 task 实例。我已经更新了 examples 和 README 相关的例子,谢谢指证。

for i := 0; i < 1000; i++ {
	wg.Add(1)
	// 创建任务
	task := &mortar.Task{
		Handler: func(v ...interface{}) {
			wg.Done()
			fmt.Println(v)
		},
	}
	// 添加任务函数的参数
	task.Params = []interface{}{i, i * 2, "hello"}
	// 将任务放入任务池
	pool.Put(task)
}

@Kline-x
Copy link
Author

Kline-x commented Jun 6, 2020

但是我试了下,在循环中创建task,开销就和不用协程池开协程差不多大了

@wazsmwazsm
Copy link
Owner

@914795561 嗯,在 task 负载很低的适合的确如此,但是 task 中如果有内存的申请相关的操作,那么就可以看出相应的效果,比如将 test 中的测试函数改为如下(当然这个例子举的相对简单):

func demoTask(v ...interface{}) {
	buf := make([]int, 5000) // 申请内存空间

	for i := 0; i < 5000; i++ { // 写内存
		buf[i] = i * 2
	}
	for i := 0; i < 100; i++ {
		atomic.AddInt64(&sum, 1)
	}
}

在任务没有参数的情形,可以先定义任务结构,然后复用该结构,此时对内存的优化是最佳的。对于有参数的任务,创建任务结构的基本开销也是少不了的,但是这个开销相对实际应用中的内存分配是要小的。协程池是一个海量任务中内存分配过多导致 gc 压力时的解决方案,解决的维度是 goroutine,通过复用 gorotine 减少内存分配。还有其它维度的解决方案,比如以单一的分配对象为维度,我们也可以用 sync.Pool 解决一些场景的内存分配的问题。要不要使用这个协程池,要看具体场景,协程池并不是在每个场景都是最优方案。

@Kline-x
Copy link
Author

Kline-x commented Jun 6, 2020

能不能将params的类型改成channel,然后通过channel来传参,task则通过消费channel获取参数

@wazsmwazsm
Copy link
Owner

@914795561 params 主要是为了适配 task handle 的形参。使用 channel 可以直接在 handle 外部定义使用,没必要修改 params 的结构。而且使用channel需要考虑一些channel阻塞的情形,这个应该完全由用户掌控。

@nianxuejie
Copy link

如何运行自定义好的函数呢? 带有多个参数 好像在任务构建时候有问题

@wazsmwazsm
Copy link
Owner

@nianxuejie 可以把例子、遇到的问题写出来。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants