Go 如何使用互斥锁高效地读写映射?
我正在读取一个包含1kk+对象的json文件,我需要组织和计数一些数据,为此我创建了两个映射,这样我可以写入和读取它,当我运行一个简单循环时,代码需要40秒才能完成,例如:Go 如何使用互斥锁高效地读写映射?,go,Go,我正在读取一个包含1kk+对象的json文件,我需要组织和计数一些数据,为此我创建了两个映射,这样我可以写入和读取它,当我运行一个简单循环时,代码需要40秒才能完成,例如: var acc int firstContent := make(map[string]int) secondContent := make(map[string]int) decoder := json.NewDecoder(bufio.NewReader(file)) for decoder.More() {
var acc int
firstContent := make(map[string]int)
secondContent := make(map[string]int)
decoder := json.NewDecoder(bufio.NewReader(file))
for decoder.More() {
var dt &MyStruct{}
decoder.Decode()
if _, ok := firstContent[dt.Name]; !ok {
firstContent["some-data"] = 1
acc++ // count the uniqueness
} else {
firstContent["some-data"] += 1
}
if _, ok := secondContent[dt.City]; !ok {
first["some-data"] = 1
} else {
first["some-data"] += 1
}
}
我尝试使用goroutines
和mutex
进行优化,以避免并发,但使用它时,需要更长的时间才能完成
var mutex = sync.RWMutex{}
for reader.More() {
var dt &MyStruct{}
reader.Decode(&dt)
go func(name string) {
mutex.Lock()
if _, ok := firstContent[name]; !ok {
firstContent[name] = 1 // need to convert to *int64, i know...
atomic.AddInt32(acc, 1)
} else {
atomic.AddInt64(firstContent[name], 1)
}
mutex.Unlock()
}(dt.Name)
go func(city string) {
mutex.Lock()
if _, ok := secondContent[city]; !ok {
secondContent[city] = 1
} else {
atomic.AddInt(secondContent[city], 1)
}
mutex.Unlock()
}(dt.City)
}
为什么要花更长的时间才能完成?因为
mutex.Lock()
?在这种情况下,我如何提高速度?您的问题无法通过一致性解决。花费大部分时间的事情是解析json,而不是计算名称。您可以说这种情况有点自相矛盾,因为您必须在单线程上读取文件。如果你能做到这一点,也许将文件拆分成更小的文件并在单独的线程上处理每个文件会有所帮助。就像上面提到的Jakub一样,你可以拆分输入文件并在单独的Goroutine(如MapReduce框架)上处理,这肯定会加快速度
另外,您是否尝试过在JSON文件中创建一个对象的go结构,并将其编组到一个对象列表中,然后从中进行计算?不确定这是否更好,但这是一个想法。1kk+是否意味着超过1000 000?你在goroutines中投入的部分是微不足道的。创建goroutine、锁定的成本远远超过实际工作的成本。运行探查器,查看程序中是否存在瓶颈。很可能输入的大小需要进行大量处理。是的@AndrewMorton,100万或更多你能给我一个如何将文件分割成块的例子吗?我认为如果你有一个包含JSON对象列表的文件,你应该将这些对象解组成它们的结构列表,那么你可以在一个goroutine上完成这一切(主线程)或切分该列表并调用一个单独的goroutine,该goroutine执行您想要的逻辑,并将结果提供给通道+等待组,以便所有人完成。