简体   繁体   English

用户如何在不更改app.config的情况下在桌面应用程序中启用Background Server GC?

[英]How can users enable Background Server GC in a desktop app without changing app.config?

I look after a WPF desktop app which many users run on varying hardware. 我照顾许多用户在不同硬件上运行的WPF桌面应用程序。 Multiple threads constantly churn through a large volume of data. 多个线程不断搅动大量数据。

Turning on .NET Framework 4.5 Background server garbage collection has shown significant performance improvements, however this comes at the cost of more memory being used and different CPU usage patterns. 启用.NET Framework 4.5后台服务器垃圾回收已显示出显着的性能改进,但这是以使用更多内存和使用不同CPU使用方式为代价的。 This is a potential problem for users with less-powerful machines, so I want to give the users who'd benefit most an opt-in to having server GC enabled instead of forcing it upon everyone. 对于使用性能较低的计算机的用户来说,这是一个潜在的问题,因此我想让受益最大的用户选择启用服务器GC,而不是强加给所有人。

The only way I've found so far to enable this is in App.Config : 到目前为止,我发现启用此功能的唯一方法是在App.Config中

<configuration>
  <runtime>
    <gcServer enabled="true"/>
  </runtime>
</configuration>

However, most users do not have permissions to edit this as the app resides within Program Files and they're not local admins. 但是,大多数用户没有权限对此进行编辑,因为该应用程序位于Program Files中,并且他们不是本地管理员。 My ideal scenario would be a friendly-worded option which could restart the app with server GC enabled and remember their choice. 我的理想情况是使用一个措辞友好的选项,该选项可以在启用服务器GC的情况下重启应用程序并记住他们的选择。

So my question is: Does anyone know of any other way to apply this setting? 所以我的问题是:是否有人知道应用此设置的任何其他方式?

I know it's probably wishful thinking - but ideally something dynamic at runtime, or maybe a command-line argument or environment variable which could be set in the context of the process. 我知道这可能是一厢情愿的想法-但理想情况下,某些东西在运行时是动态的,或者是可以在过程上下文中设置的命令行参数或环境变量。 There are hints of this existing in CoreCLR with the complus_gcServer env variable . 带有complus_gcServer env变量CoreCLR中存在此提示。

I've read about global system settings which can enable this on the machine but I don't want to risk impacting any other apps and causing other adverse affects, I only want this to apply to my app. 我已经阅读了可以在计算机上启用此功能的全局系统设置,但我不想冒险影响任何其他应用程序并造成其他不利影响,我只希望将此应用于我的应用程序。

As a last resort I could deploy two copies of the EXE with different config files and a launcher to choose the correct version to run, this seems extreme though. 作为最后的选择,我可以使用不同的配置文件和启动程序来部署EXE的两个副本,以选择要运行的正确版本,但这似乎很极端。

Thanks for reading, any ideas welcome! 感谢您的阅读,欢迎任何想法!

Here is an alternate suggestion. 这是一个替代建议。 Leave server GC enabled as you have done. 完成后,保持服务器GC处于启用状态。 Then based on a user defined setting force GC to run if app memory goes above a certain threshold that you determine as the critical level. 然后,根据用户定义的设置,如果应用程序内存超过确定为关键级别的某个阈值,则强制GC运行。

Mind you if you follow this path you are effectively stating that you have better knowledge of when garbage collection should run that the CLR does. 请注意,如果您遵循这条路径,则实际上是在说您对CLR应该何时运行垃圾收集有更好的了解。 Most often than not I've found that the CLR does a better job on its own than when we interfere with it. 通常,我发现CLR本身比我们进行干预时做得更好。

Code to check memory usage and run GC across either all generations or a specified generation 用于检查内存使用情况并在所有世代或指定世代中运行GC的代码

if (Math.Abs(DateTime.Now.Subtract(MemUsageLastCheckTime).TotalMinutes) > 5d)
{
    long UsedMemory;
    //UsedMemory = GC.GetTotalMemory(false); // Not as reliable
    UsedMemory = System.Diagnostics.Process.GetCurrentProcess().PagedMemorySize64;
    if (UsedMemory > 1073741824) // One GB in bytes 1 X 1024 X 1024 X 1024
    {
        GC.Collect(); // Collect all generations
        //GC.Collect(2,GCCollectionMode.Forced);; Or collect a specific generation and force it to run now
    }
    MemUsageLastCheckTime = DateTime.Now;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM