【问题标题】:Mutable application context可变的应用程序上下文
【发布时间】:2018-08-19 04:59:38
【问题描述】:

我正在构建一个需要大量值集合来计算答案的 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时会被释放?

【问题讨论】:

  • 你必须展示你的代码,至少是其中的一部分。我们不能在不知道你在做什么的情况下说你做错了什么。更好的是,构建一个最小的可重现示例。

标签: f# garbage-collection suave


【解决方案1】:

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?

【讨论】:

    猜你喜欢
    • 2015-08-31
    • 1970-01-01
    • 2013-08-23
    • 1970-01-01
    • 1970-01-01
    • 2016-05-20
    • 2013-02-06
    • 2012-02-24
    • 1970-01-01
    相关资源
    最近更新 更多