【问题标题】:Speeding up creation of nested structs加快嵌套结构的创建
【发布时间】:2020-12-12 01:26:30
【问题描述】:

我的代码按预期工作,我只是想加快速度。

我有一个包含数百万传感器测量值的数据库表。 当我在数据库中查询过去 2 个月的测量值(按传感器名称排序)时,我得到了大约 300,000 个结果。

然后我继续逐步检查结果并希望从数据中创建嵌套结构对象。 这里有一些较短的伪代码:

struct Measurement {
  var date: Int
  var temp: Double?
  ... 
}

struct Sensor {
  var sensorName: String
  var measurements: [Measurement]
}

var sensors:[Sensor] = []

...

for r in dbResults {
  ...
  let m = Measurement(date: r.date, temp: r.temp1, ... )

  if let index = sensors.firstIndex(where: { $0.sensorName = r.name }) {
    sensors[index].measurements.append(m)
  } else {
    sensors.append(Sensor(sensorName: r.name, measurements: [m]))
  }
}

然而,这相当慢。循环完成大约需要一分钟。 有没有办法加快这个过程?我假设.firstIndex 需要太长时间。 我正在考虑在并行线程上创建对象,但我不确定如何最好地做到这一点,而不会在检查 .firstIndex 时冒竞争条件的风险。

感谢您的任何想法

【问题讨论】:

  • 数据中有多少个传感器?如果 300,000 次测量分布在 10 个传感器上,我怀疑firstIndex 花费的时间太长。您是否使用 Instruments 来检查什么耗时过长?
  • 绝对同意以上观点。当然,如果有数千个传感器,那么.firstIndex(where:) 是低效的。您可以利用它们已排序的事实,只查看最后一个索引,而不是搜索第一个匹配项。提前为阵列保留空间,而不是逐步增长它们也可能是有意义的。很大程度上取决于数据的分布
  • 传感器的数量各不相同,但大多数时候有 4,000-6,000 个。将尝试last 的想法。如何在swift中保留空间?

标签: arrays swift struct


【解决方案1】:

我会将存储更改为字典

var sensors:[String: Sensor] = [:]

...

for r in dbResults {
  ...
  let m = Measurement(date: r.date, temp: r.temp1, ... )

  sensors[r.name, default: Sensor(sensorName: r.name, 
      measurements: [])].measurements.append(m)
}

【讨论】:

  • 不知道您可以为数组元素设置默认值。这是完美的,解决了速度问题。精彩的!谢谢
【解决方案2】:

不要自己重写Dictionary(grouping:by:)。其他人免费为您维护!

var 放在这里:?

let sensors = Dictionary(grouping: dbResults, by: \.name).map {
  Sensor(
    sensorName: $0,
    measurements: $1.map { .init(date: $0.date, temp: $0.temp1) }
  )
}

【讨论】:

    猜你喜欢
    • 2023-03-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多