我正在构建一个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时会释放内存?
答案 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?