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 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()
?在这种情况下如何提高速度?
解决方案
就像上面的 Jakub 所说,您可以将输入文件和进程拆分到单独的 goroutine(如 MapReduce 框架)上,这肯定会加快速度。
另外,您是否尝试过在 JSON 文件中创建对象的 go-struct 并将其编组到它们的列表中并从那里进行计算?不确定这是否会更好,但这是一个想法。
推荐阅读
- ios - 使用我的 React Native iPhone 应用程序无需交互即可自动打印到热敏打印机(例如 Brother QL)的 API/SDK?
- reactjs - 测试使用上下文的组件
- xml - 将代码/XML/JSON 从 Visual Studio 代码复制到 MS Word 或 Outlook 时保留格式
- python - FileNotFoundError:[Errno 2] 如果将文件保存在 OneDrive 文件夹中,则没有此类文件或目录
- html - 如何抵消 Markdown 链接锚以调整 Jekyll 中的固定标头?
- python - Python中查找可迭代元素是否是最后一个的标准方法?
- c# - 如何限制相机在 Y 轴上的旋转?帮我 §
- javascript - DataTable rows.every 函数问题
- transformation - 如何改进这个平方根转换代码?
- python - curve_fit 使调用 func 引发 IndexError