【发布时间】:2023-03-13 04:10:01
【问题描述】:
在 Go 中使用正则表达式时,我遇到了巨大的内存问题:
Showing top 20 nodes out of 34
flat flat% sum% cum cum%
1.53GB 25.03% 25.03% 1.53GB 25.03% regexp/syntax.(*compiler).inst
1.43GB 23.29% 48.31% 1.43GB 23.29% regexp/syntax.(*parser).newRegexp
1.10GB 17.99% 66.31% 1.10GB 17.99% regexp.onePassCopy
0.53GB 8.67% 74.97% 0.53GB 8.67% regexp/syntax.(*Regexp).Simplify
0.39GB 6.44% 81.41% 0.90GB 14.74% regexp.makeOnePass
0.29GB 4.76% 86.17% 0.29GB 4.76% regexp.newQueue
0.19GB 3.13% 89.30% 0.22GB 3.54% regexp.makeOnePass.func1
0.17GB 2.79% 92.09% 6.10GB 99.54% regexp.compile
0.14GB 2.22% 94.31% 0.25GB 4.09% regexp/syntax.(*parser).collapse
0.14GB 2.21% 96.52% 0.14GB 2.21% regexp/syntax.(*parser).push
0.10GB 1.66% 98.17% 1.80GB 29.37% regexp/syntax.Parse
0.04GB 0.69% 98.86% 0.10GB 1.59% regexp/syntax.(*compiler).init
0 0% 98.86% 6.13GB 100% bicctopostgres/app.Test_prepareRecordsToInsert
0 0% 98.86% 6.10GB 99.54% bicctopostgres/app.TypeIs
0 0% 98.86% 6.10GB 99.54% bicctopostgres/app.evalColumn
0 0% 98.86% 6.11GB 99.74% bicctopostgres/app.getColumnsHeaderData
0 0% 98.86% 1.42GB 23.12% bicctopostgres/app.isDate
0 0% 98.86% 0.61GB 10.00% bicctopostgres/app.isInteger
0 0% 98.86% 1.09GB 17.85% bicctopostgres/app.isReal
0 0% 98.86% 2.98GB 48.58% bicctopostgres/app.isTimestamp
我正在构建一个程序来解析 csv 文件,检查每一列是否为空和数据类型(最后一位是用正则表达式生成的),生成 Postgres 表并加载记录。创建数据库表时忽略没有数据的列。
但是我遇到了一个巨大的瓶颈,即对于仅 2000 条记录,我将使用 6GB 的内存来处理与正则表达式相关的内容。
这是一个检查数据是否为时间戳的函数示例:
//isTimestamp returns true if the string is exacly: 9999-99-99 99:99:99.999999 .
func isTimestamp(s *string) bool {
e := `(?i)^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6}$`
var isDesired = regexp.MustCompile(e)
return isDesired.MatchString(*s)
}
然后检查类型的主要功能是:
//TypeIs returns the underlying data type of the string, if it's a string also returns the string length, otherwise is zero.
func TypeIs(s *string) (dataType string, stringLength int) {
if isInteger(s) {
return "INTEGER", 0
}
if isReal(s) {
return "REAL", 0
}
if isDate(s) {
return "DATE", 0
}
if isTimestamp(s) {
return "TIMESTAMP", 0
}
return "TEXT", len(*s)
}
也许我的正则表达式太糟糕了?他们工作,但也许它太暴力了。
有什么建议吗?谢谢!
【问题讨论】:
-
您有一个静态正则表达式,但每次函数不必要地运行时,您都会重新编译它。只需编译一次并将其保存在包 var 中以供重复使用。
-
@Adrian 谢谢!
标签: regex go optimization memory