【问题标题】:CSV to date and floatCSV 迄今为止和浮动
【发布时间】:2019-02-17 20:48:41
【问题描述】:

我目前正在编写一个小程序,它将 CSV 文件转换为用于进一步处理的结构。 csv 行看起来像这样

20140102,09:30,38.88,38.88,38.82,38.85,67004

我有 500 个文件,每个文件大约 20-30 MB。 我的代码工作得很好,但我不禁想知道是否没有比我现在正在做的更好的方法来转换这些文件。 首先读取文件并转换为csv记录(伪代码)

    data, err := ioutil.ReadFile(path)
    if err != nil {
        ... 
    }
    r := csv.NewReader(bytes.NewReader(data))
    records, err := r.ReadAll()
    if err != nil {
        ... 
    }

然后遍历所有记录并做

    parsedTime, err := time.Parse("2006010215:04", record[0]+record[1])
    if err != nil {
        return model.ZorroT6{}, time.Time{}, err
    }

    t6.Date = ConvertToOle(parsedTime)
    if open, err := strconv.ParseFloat(record[2], 32); err == nil {
        t6.Open = float32(open)
    }
    if high, err := strconv.ParseFloat(record[3], 32); err == nil {
        t6.High = float32(high)
    }
    if low, err := strconv.ParseFloat(record[4], 32); err == nil {
        t6.Low = float32(low)
    }
    if close, err := strconv.ParseFloat(record[5], 32); err == nil {
        t6.Close = float32(close)
    }
    if vol, err := strconv.ParseInt(record[6], 10,32); err == nil {
        t6.Vol = int32(vol)
    }

例如,我必须通过 []byte -> string -> float64 -> float32 来获取我的浮点值。我可以做些什么来改进这段代码?

编辑:为了明确我并不真正需要来提高性能,我只是更好地尝试了解 Go 以及可以应用于此类问题的性能优化。例如,当我有一个字节切片并想要一个 float32 时,创建大量字符串和 float64 似乎需要很多开销。

【问题讨论】:

  • 我认为代码不需要改进。现在需要多长时间,您希望需要多长时间?您是否已对您的程序进行了概要分析,您确定这是瓶颈所在吗?
  • 我真的不需要提高速度,但是为了更好地理解go,我想尝试一下。我已经分析了应用程序,目前大部分时间都花在了 readRecord(由 readAll 调用)、time.Parse 和 parseFloat。

标签: performance go


【解决方案1】:

我发现只有一个问题需要解决:

不要将ioutil.ReadFile 与bytes.NewReader 一起使用。将所有内容读入内存,文件大时效率低。

相反,使用os.Open(file),它完美地提供了csv.NewReader 可以使用的io.Reader。不要忘记关闭文件并处理错误。

如果您仍想提高性能:

  1. 由于您的 csv 文件是固定格式,因此可以使用 bufio 提供的原始字节而不是 csv。

  2. 您可以复制并粘贴strconv 和time 中的底层代码,以避免不需要的通用代码。

但我认为他们不值得麻烦。

【讨论】:

  • 谢谢,我会看看使用 os.Open() 代替。我实际上很快就查看了 bufio,但是由于我仍然找不到将 []byte 从 bufio 转换为 float32 或 time 而不经过字符串的方法,所以我再也没有走得更远。但我想我可以结合 1) 和 2),以及采用 []byte 而不是字符串的函数。可能是一个未雨绸缪的好项目;-) 再次感谢,非常感谢您的回复。
  • @Daniel 请注意,这可能会损害您未来的维护。
  • 当然,对于生产系统,我不会这样做。更多的是作为一种学习体验,并了解您可以从提取和修改内部 API 等更极端的措施中获得什么样的性能提升。该代码目前在大约 100 秒内解析约 10GB 的数据,这已经足够快了。
  • 我试过这样做,只是为了好玩。让 parseFloat 直接返回一个 float32 对性能来说绝对是nothing。将其更改为接受 []byte 而不是字符串将分配减半,因此我想如果您对此有疑问,可能值得进一步探索。但就像你已经说过的;可能不值得麻烦。
猜你喜欢
  • 2017-08-14
  • 1970-01-01
  • 2014-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多