2

我正在构建一个需要大量值来计算答案的 REST 后端。此集合在启动时下载,然后按需下载,但需要每天更新几次。我不知道如何应对这种可变状态。我已经在 main 函数中尝试了 ref 和 mutable 变量,但是旧集合永远不会被释放,并且内存使用量在不受控制的情况下增长。

处理这种可变状态的正确方法是什么?

编辑

在准备我正在做的事情的样本时,我发现了第一个错误。我在做:

let sqlfeed() = use cmd = new SqlFeedType(connectionString) Some (cmd.Execute() |> Seq.toList)

现在我正在做我正在做这样的事情:

let sqlfeed() = Some (using (new SqlFeedType(connectionString)) (fun cmd -> cmd.Execute() |> Seq.toList))

然后

[<EntryPoint>]
let main argv =
    let optionSqlFeed = ref None
    let app =
        choose [
            Filters.path "/sqlfeed" >=> warbler (fun ctx -> 
                match !optionSqlFeed with
                | None ->
                    optionSqlFeed := sqlfeed()
                | Some a ->
                    optionSqlFeed := None
                Successful.OK "done" ) 
         ]
    startWebServer defaultConfig app

之前,当我调用 sqlfeed 并下载数据时,我看到内存增加了。在交替分配给 None 的连续调用中,内存不会被释放,并且总使用量只会攀升。现在,当我调用 sqlfeed 并将 None 分配给可变变量时,内存仍然没有被释放,但是在下一次调用 sqlfeed 时,内存被释放。

为什么我分配None时不会释放内存,但再次调用sqlfeed时会释放内存?

4

1 回答 1

0

GC 的运行时间不确定。当您sqlfeed()再次调用时,它会对应用程序施加内存压力,我敢打赌这有时会触发垃圾收集,而将变量设置为无值不会占用额外的内存。

存在的物理内存量会影响垃圾收集发生的时间,如果可能的话,它是惰性的 - CLR 垃圾收集器频率和系统内存可用

您可以在将变量设置为时自行触发 GC,None但这可能不是一个好主意 -何时可以调用 GC.Collect?

来自:了解 .NET 中的垃圾收集

GC.Collect() 将只运行垃圾收集的跟踪部分并将项目添加到终结器队列,但不会调用由另一个线程处理的类型的终结器。

如果您希望根据需要释放当前值而不是无限期地持有当前值,请使用WeakReference Wea​​kReference 是否可以提供良好的缓存?

于 2019-02-19T16:22:50.577 回答