regex - 优化 Go 中正则表达式的内存消耗
问题描述
在 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 isDesired = regexp.MustCompile(`(?i)^[0-9]{4}-[0-9]{2}-[0-9]{2} [0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{6}$`)
func isTimestamp(s *string) bool {
return isDesired.MatchString(*s)
}
推荐阅读
- android - Google 开发者控制台中的“我们检测到您的应用正在使用旧版本的 Google Play 开发者 API”警告是什么?
- android - 如何从网络中获取频段信息?
- mysql - 插入mysql db时获取Last Insert Id的最可靠方法是什么
- jsf - 如何在 p:column 中应用正则表达式?
- c++ - 如何根据模板类型参数调用不同的函数?
- php - 更新到 php7.2 zip 无限创建文件
- scala - Spark tests failing when running with sbt test
- c - C RPC 服务器 malloc 内存损坏
- javascript - 如何根据日期过滤数据?
- c# - 如何使用 ASP.NET Core 中的自定义验证在索引处获取属性?