可变的应用程序上下文

时间:2018-03-10 20:38:57

标签: f# garbage-collection suave

我正在构建一个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并下载数据时,我看到内存上升了。在交替分配为无的连续呼叫中,将不会释放内存并且总使用率刚刚攀升。现在,当我调用sqlfeed并为可变变量赋值None时,内存仍然没有被释放,但是在下次调用sqlfeed时,内存被释放。

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

1 个答案:

答案 0 :(得分:0)

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

当发生垃圾收集时,当前的物理内存量会受到影响,并且如果可能的话,它会变得很懒-CLR Garbage Collector frequency and system memory available

将变量设置为None时,您可以自己触发GC,但这可能不是一个好主意-When is it acceptable to call GC.Collect?

来自:Understanding garbage collection in .NET

  

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

如果您希望根据需要释放当前值,而不是无限期保留,请使用WeakReference Does WeakReference make a good cache?