我有一台运行 Windows Server 2008 R2 x64的服务器,带有4GB的RAM,可容纳大约2-3百万个文件,其中大部分是图像文件.

在一个星期的过程中,我注意到服务器上的应用程序由于内存不足而导致对磁盘的过度分页而导致爬行速度变慢,这会对当前在其上运行的所有服务产生连锁效应,导致主要问题性能问题.

在任务管理器中进行调查后,我注意到几乎所有4GB都在使用中,但是当您查看“进程”选项卡时,所有内存使用量的总和不会累加,最多只有1.5GB应该在使用中.

使用Google查找解决方案,似乎大多数RAM都用在“Metafile”中,它是文件系统上文件的NTFS信息缓存,因此系统不必再次向MFT查询信息.此缓存永远不会在任务管理器中清除或标记为“缓存”,或在Sysinternal的RamMap中标记为“待机”.

有a suggestion安装KB979149修复程序,但在尝试安装它时,它说“此更新不适用于您的计算机”.

到目前为止,我发现的唯一临时修复是:

>每隔1-3天使用来自Sysinternals的RAMmap到“清空系统工作集”,在任务管理器中将缓存标记为“待机”和“缓存”,以便其他应用程序可以使用RAM.
>重启机器,这是不受欢迎的,因为此服务器正在为公共网站提供服务.

目前我不得不每隔几天执行2.修复以防止它达到瓶颈水平.

之前:(使用800MB RAM – 其他应用程序无法使用此RAM)

之后:(800MB RAM标记为缓存 – 可用于其他应用程序)

所以我的问题是:是否存在任何方法来限制此元文件的RAM使用?

处理此问题的最佳方法是使用 SetSystemFileCacheSize API作为 MSKB976618 instructs MS KB976618 used to instruct.

不要定期清除缓存

使用SetSystemFileCacheSize函数而不是定期清除缓存可以提高性能和稳定性.定期清除缓存将导致过多的元文件和其他信息从内存中清除,并且窗口必须从HDD重新读取所需信息到RAM中.每当您清除缓存时,这会在几秒钟内导致性能突然严重下降,随后性能会随着内存填充元文件数据而慢慢降低.

使用SetSystemFileCacheSize函数设置最小值和最大值,这将导致窗口将多余的旧元文件数据标记为正常缓存功能可根据当前资源需求和正常缓存优先级使用或丢弃的备用内存.这也允许比你设置的活动内存最多的元文件数据,如果windows在没有使用内存的情况下保留足够的可用内存,则将内存作为备用数据.这是保持系统性能特征始终良好的理想情况.

MS不支持第三方程序

如果您像我一样并且不想在生产服务器上运行来自某个未知第三方的二进制文件,那么您需要一个正式的MS工具或一些代码,您可以在这些服务器上运行之前检查它们.用于2008 R2的DynCache工具实际上不可能从M $获得而无需支付支持案例,坦率地说,基于2008年的代码,它似乎过于臃肿,因为Windows已经具有动态调整大小所需的内置逻辑缓存,它只需要知道您的系统适当的最大值.

解决所有上述问题

我写了一个适用于64位机器的powershell脚本.您需要以具有提升权限的管理员身份运行它.您应该可以在任何x64 Windows Vista / Server 2008上运行它,包括任意数量的RAM的10 / Server 2012 R2.您无需安装任何其他软件,因此可以使MS完全支持您的服务器/工作站.

您应该在每次启动时使用提升的权限运行此脚本,以使设置成为永久设置. Windows任务计划程序可以为您执行此操作.如果Windows安装在虚拟机内,并且您更改分配给该VM的RAM量,则还应在更改后运行它.

即使在生产使用中,您也可以在正在运行的系统上随时运行此脚本,而无需重新启动系统或关闭任何服务.

# Filename: setfc.ps1
$version = 1.1

#########################
# Settings
#########################

# The percentage of physical ram that will be used for SetSystemFileCache Maximum
$MaxPercent = 12.5

#########################
# Init multipliers
#########################
$OSBits = ([system.intPtr]::Size) * 8
switch ( $OSBits)
{
    32 { $KiB = [int]1024 }
    64 { $KiB = [long]1024 }
    default {
        # not 32 or 64 bit OS. what are you doing??
        $KiB = 1024 # and hope it works anyway
        write-output "You have a weird OS which is $OSBits bit. Having a go anyway."
    }
}
# These values "inherit" the data type from $KiB
$MiB = 1024 * $KiB
$GiB = 1024 * $MiB
$TiB = 1024 * $GiB
$PiB = 1024 * $TiB
$EiB = 1024 * $PiB


#########################
# Calculated Settings
#########################

# Note that because we are using signed integers instead of unsigned
# these values are "limited" to 2 GiB or 8 EiB for 32/64 bit OSes respectively

$PhysicalRam = 0
$PhysicalRam = [long](invoke-expression (((get-wmiobject -class "win32_physicalmemory").Capacity) -join '+'))
if ( -not $? ) {
    write-output "Trying another method of detecting amount of installed RAM."
 }
if ($PhysicalRam -eq 0) {
    $PhysicalRam = [long]((Get-WmiObject -Class Win32_ComputerSystem).TotalPhysicalMemory) # gives value a bit less than actual
}
if ($PhysicalRam -eq 0) {
    write-error "Cannot Detect Physical Ram Installed. Assuming 4 GiB."
    $PhysicalRam = 4 * $GiB
}
$NewMax = [long]($PhysicalRam * 0.01 * $MaxPercent)
# The default value
# $NewMax = 1 * $TiB


#########################
# constants
#########################

# Flags bits
$FILE_CACHE_MAX_HARD_ENABLE     = 1
$FILE_CACHE_MAX_HARD_disABLE    = 2
$FILE_CACHE_MIN_HARD_ENABLE     = 4
$FILE_CACHE_MIN_HARD_disABLE    = 8


################################
# C# code
# for interface to kernel32.dll
################################
$source = @"
using System;
using System.Runtime.InteropServices;

namespace MyTools
{
    public static class cache
    {
        [DllImport("kernel32",SetLastError = true,CharSet = CharSet.Unicode)]
        public static extern bool GetSystemFileCacheSize(
            ref IntPtr lpMinimumFileCacheSize,ref IntPtr lpMaximumFileCacheSize,ref IntPtr lpFlags
            );

        [DllImport("kernel32",CharSet = CharSet.Unicode)]
        public static extern bool SetSystemFileCacheSize(
          IntPtr MinimumFileCacheSize,IntPtr MaximumFileCacheSize,Int32 Flags
        );

        [DllImport("kernel32",CharSet = CharSet.Unicode)]
        public static extern int GetLastError();

        public static bool Get( ref IntPtr a,ref IntPtr c,ref IntPtr d )
        {
            IntPtr lpMinimumFileCacheSize = IntPtr.Zero;
            IntPtr lpMaximumFileCacheSize = IntPtr.Zero;
            IntPtr lpFlags = IntPtr.Zero;

            bool b = GetSystemFileCacheSize(ref lpMinimumFileCacheSize,ref lpMaximumFileCacheSize,ref lpFlags);

            a = lpMinimumFileCacheSize;
            c = lpMaximumFileCacheSize;
            d = lpFlags;
            return b;
        }


        public static bool Set( IntPtr MinimumFileCacheSize,Int32 Flags )
        {
            bool b = SetSystemFileCacheSize( MinimumFileCacheSize,MaximumFileCacheSize,Flags );
            if ( !b ) {
                Console.Write("SetSystemFileCacheSize returned Error with GetLastError = ");
                Console.WriteLine( GetLastError() );
            }
            return b;
        }
    }

    public class AdjPriv
    {
        [DllImport("advapi32.dll",ExactSpelling = true,SetLastError = true)]
        internal static extern bool AdjustTokenPrivileges(IntPtr htok,bool disall,ref TokPriv1Luid newst,int len,IntPtr prev,IntPtr relen);

        [DllImport("advapi32.dll",SetLastError = true)]
        internal static extern bool OpenProcesstoken(IntPtr h,int acc,ref IntPtr phtok);

        [DllImport("advapi32.dll",SetLastError = true)]
        internal static extern bool LookupPrivilegeValue(string host,string name,ref long pluid);

        [StructLayout(LayoutKind.Sequential,Pack = 1)]
        internal struct TokPriv1Luid
        {
            public int Count;
            public long Luid;
            public int Attr;
        }
        internal const int SE_PRIVILEGE_ENABLED = 0x00000002;
        internal const int SE_PRIVILEGE_disABLED = 0x00000000;
        internal const int TOKEN_QUERY = 0x00000008;
        internal const int TOKEN_ADJUST_PRIVILEGES = 0x00000020;

        public static bool EnablePrivilege(long processHandle,string privilege,bool disable)
        {
            bool retVal;
            TokPriv1Luid tp;
            IntPtr hproc = new IntPtr(processHandle);
            IntPtr htok = IntPtr.Zero;
            retVal = OpenProcesstoken(hproc,TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,ref htok);
            tp.Count = 1;
            tp.Luid = 0;
            if(disable)
            {
                tp.Attr = SE_PRIVILEGE_disABLED;
            } else {
                tp.Attr = SE_PRIVILEGE_ENABLED;
            }
            retVal = LookupPrivilegeValue(null,privilege,ref tp.Luid);
            retVal = AdjustTokenPrivileges(htok,false,ref tp,IntPtr.Zero,IntPtr.Zero);
            return retVal;
        }
    }
}
"@
# Add the c# code to the powershell type deFinitions
Add-Type -TypeDeFinition $source -Language CSharp

#########################
# Powershell Functions
#########################
function output-flags ($flags)
{
    Write-output ("FILE_CACHE_MAX_HARD_ENABLE  : " + (($flags -band $FILE_CACHE_MAX_HARD_ENABLE) -gt 0) )
    Write-output ("FILE_CACHE_MAX_HARD_disABLE : " + (($flags -band $FILE_CACHE_MAX_HARD_disABLE) -gt 0) )
    Write-output ("FILE_CACHE_MIN_HARD_ENABLE  : " + (($flags -band $FILE_CACHE_MIN_HARD_ENABLE) -gt 0) )
    Write-output ("FILE_CACHE_MIN_HARD_disABLE : " + (($flags -band $FILE_CACHE_MIN_HARD_disABLE) -gt 0) )
    write-output ""
}

#########################
# Main program
#########################

write-output ""

#########################
# Get and set privilege info
$ProcessId = $pid
$processHandle = (Get-Process -id $ProcessId).Handle
$Privilege = "SeIncreaseQuotaPrivilege"
$disable = $false
Write-output ("Enabling SE_INCREASE_QUOTA_NAME status: " + [MyTools.AdjPriv]::EnablePrivilege($processHandle,$Privilege,$disable) )

write-output ("Program has elevated privledges: " + ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator") )
write-output ""
whoami /PRIV | findstr /I "SeIncreaseQuotaPrivilege" | findstr /I "Enabled"
if ( -not $? )  {
    write-error "user Security Token SE_INCREASE_QUOTA_NAME: disabled`r`n"
}
write-output "`r`n"


#########################
# Get Current Settings
# Init variables
$SFCMin = 0
$SFCMax = 0
$SFCFlags = 0
#Get Current values from kernel
$status = [MyTools.cache]::Get( [ref]$SFCMin,[ref]$SFCMax,[ref]$SFCFlags )
#typecast values so we can do some math with them
$SFCMin = [long]$SFCMin
$SFCMax = [long]$SFCMax
$SFCFlags = [long]$SFCFlags
write-output "Return values from GetSystemFileCacheSize are: "
write-output "Function Result : $status"
write-output "            Min : $SFCMin"
write-output ("            Max : $SFCMax ( " + $SFCMax / 1024 / 1024 / 1024 + " GiB )")
write-output "          Flags : $SFCFlags"
output-flags $SFCFlags


#########################
# Output our intentions
write-output ("Physical Memory Detected : $PhysicalRam ( " + $PhysicalRam / $GiB + " GiB )")
write-output ("Setting Max to " + $MaxPercent + "% : $NewMax ( " + $NewMax / $MiB + " MiB )`r`n")

#########################
# Set new settings
$SFCFlags = $SFCFlags -bor $FILE_CACHE_MAX_HARD_ENABLE # set max enabled
$SFCFlags = $SFCFlags -band (-bnot $FILE_CACHE_MAX_HARD_disABLE) # unset max dissabled if set
# or if you want to override this calculated value
# $SFCFlags = 0
$status = [MyTools.cache]::Set( $SFCMin,$NewMax,$SFCFlags ) # calls the c# routine that makes the kernel API call
write-output "Set function returned: $status`r`n"
# if it was successfull the new SystemFileCache maximum will be NewMax
if ( $status ) {
    $SFCMax = $NewMax
}


#########################
# After setting the new values,get them back from the system to confirm
# Re-Init variables
$SFCMin = 0
$SFCMax = 0
$SFCFlags = 0
#Get Current values from kernel
$status = [MyTools.cache]::Get( [ref]$SFCMin,[ref]$SFCFlags )
#typecast values so we can do some math with them
$SFCMin = [long]$SFCMin
$SFCMax = [long]$SFCMax
$SFCFlags = [long]$SFCFlags
write-output "Return values from GetSystemFileCacheSize are: "
write-output "Function Result : $status"
write-output "            Min : $SFCMin"
write-output ("            Max : $SFCMax ( " + $SFCMax / 1024 / 1024 / 1024 + " GiB )")
write-output "          Flags : $SFCFlags"
output-flags $SFCFlags

顶部附近有一行表示$MaxPercent = 12.5,它将新的最大工作集(活动内存)设置为总物理RAM的12.5%. Windows将根据系统需求动态调整活动内存中元文件数据的大小,因此您无需动态调整此最大值.

这不会解决您对映射文件缓存过大的任何问题.

我还制作了一个GetSystemFileCacheSize powershell脚本并将其发布
https://stackoverflow.com/questions/5898843/c-sharp-get-system-file-cache-size/17875550#17875550

编辑:我还应该指出,您不应该多次从同一个PowerShell实例运行这两个脚本中的任何一个,否则您将收到已经进行了Add-Type调用的错误.

编辑:更新了SetSystemFileCacheSize脚本到版本1.1,为您计算适当的最大缓存值,并具有更好的状态输出布局.

编辑:现在我升级了我的Windows 7笔记本电脑,我可以告诉你该脚本在Windows 10中成功运行,但我还没有测试它是否仍然需要.但即使在移动虚拟机硬盘文件时,我的系统仍然稳定.

windows-server-2008-r2 – Windows Server 2008 R2图元文件RAM使用的更多相关文章

  1. 详解使用双缓存解决Canvas clearRect引起的闪屏问题

    这篇文章主要介绍了详解使用双缓存解决Canvas clearRect引起的闪屏问题的相关资料,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. 利用Node实现HTML5离线存储的方法

    这篇文章主要介绍了利用Node实现HTML5离线存储的方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. HTML5 Web缓存和运用程序缓存(cookie,session)

    这篇文章主要介绍了HTML5 Web缓存和运用程序缓存(cookie,session),小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. 详解前端HTML5几种存储方式的总结

    本篇文章主要介绍了前端HTML5几种存储方式的总结 ,主要包括本地存储localstorage,本地存储sessionstorage,离线缓存(application cache),Web SQL,IndexedDB。有兴趣的可以了解一下。

  5. 在iOS上,缓存绘制的屏幕图像并显示它的最快方法是什么?

    我没有让drawRect每次重绘数千个点,我认为有几种方法可以“在屏幕上缓存图像”和任何其他绘图,我们将添加到该图像,并在drawRect时显示该图像:>使用BitmapContext并绘制到位图,并在drawRect中绘制此位图.>使用CGLayer并在drawRect中绘制CGLayer,这可能比方法1快,因为此图像缓存在图形卡中(并且它不会计入iOS上“内存警告”的RAM使用情况?

  6. ios – NSURLCache和数据保护

    我正在尝试保护存储在NSURLCache中的敏感数据.我的应用程序文件和CoreDatasqlite文件设置为NSFileProtectionComplete.但是,我无法将NSURLCache文件数据保护级别更改为NSFileProtectionCompleteUntilFirstUserAuthentication以外的任何其他级别.这会在设备锁定时暴露缓存中的任何敏感数据.我需要缓存响应,以

  7. iOS Safari多久会清除一次缓存?

    我使用移动Safari缓存来存储我想要持久化的一些数据,所以我希望它们能够在Safari重启和iOS重启后继续存在.但是我已经阅读了somenew和someold报告,Safari在Safari重新启动时清除了它的缓存.但我对Safari8.3的非科学测试表明,有时这个缓存实际上不仅可以在应用程序重启后生存,而且甚至可以重启iOS(!).所以我在这一点上有点困惑.iOSSafari缓存清除的规则是否记录在某处?你们中有谁知道他们并且可以向我解释他们吗?解决方法希望有人发现我错了但是……

  8. ios – 如何获取缓存图像SDWebImage的数据

    我正在使用SDWebImage库来缓存我的UICollectionView中的Web图像:但我想将缓存的图像本地保存在文件中,而不是再次下载它们有没有办法获取缓存图像的数据解决方法SDWebImage默认自动缓存下载的图像.您可以使用SDImageCache从缓存中检索图像.当前应用会话有一个内存缓存,它会更快,并且有磁盘缓存.用法示例:还要确保在文件中导入SDWebImage.(如果您使用的是Swift/Carthage,它将导入WebImage

  9. 缓存 – NSURLCache在iOS5上提供不一致的结果,似乎是随机的

    我刚刚花了很长时间在NSURLCache尖叫我,所以我提供了一些建议,希望别人能够避免我的不幸.这一切都足够合理.我的新应用程序项目只针对iOS5及更高版本,所以我认为我可以利用新的NSURLCache实现我所有的Web缓存需求.我需要一个NSURLCache的自定义子类来处理一些特殊的任务,但是这似乎都被API的有力支持.快速阅读文档,我会参加比赛:我认为一个8MB缓存启动是很好的,我会用更大的

  10. iOS与解析. PFUser.currentuser()没有缓存.应用程序重新启动后返回零

    我正在迅速地用Parse构建一个应用程序.在应用程序停止后,PFUser.currentuser()总是返回nil,并再次运行.我正在使用iOS模拟器,并且启用了本地数据存储.我正在使用这样的东西–而我正在使用的登录当前用户保持到应用程序重新启动,然后重置为零.我甚至试图固定当前用户,但它不起作用.如何检查当前用户是否在本地缓存.任何帮助将不胜感激.谢谢.解决方法对我来说,原因只是以下部分没有执行.注意多线程.通常是这个原因.

随机推荐

  1. static – 在页面之间共享数据的最佳实践

    我想知道在UWP的页面之间发送像’selectedItem’等变量的最佳做法是什么?创建一个每个页面都知道的静态全局变量类是一个好主意吗?

  2. .net – 为Windows窗体控件提供百分比宽度/高度

    WindowsForm开发的新手,但在Web开发方面经验丰富.有没有办法为Windows窗体控件指定百分比宽度/高度,以便在用户调整窗口大小时扩展/缩小?当窗口调整大小时,可以编写代码来改变控件的宽度/高度,但我希望有更好的方法,比如在HTML/CSS中.在那儿?

  3. 使用Windows Azure查询表存储数据

    我需要使用特定帐户吗?>将应用程序部署到Azure服务后,如何查询数据?GoogleAppEngine有一个数据查看器/查询工具,Azure有类似的东西吗?>您可以看到的sqlExpressintance仅在开发结构中,并且一旦您表示没有等效,所以请小心使用它.>您可以尝试使用Linqpad查询表格.看看JamieThomson的thispost.

  4. windows – SetupDiGetClassDevs是否与文档中的设备实例ID一起使用?

    有没有更好的方法可以使用DBT_DEVICEARRIVAL事件中的数据获取设备的更多信息?您似乎必须指定DIGCF_ALLCLASSES标志以查找与给定设备实例ID匹配的所有类,或者指定ClassGuid并使用DIGCF_DEFAULT标志.这对我有用:带输出:

  5. Windows Live ID是OpenID提供商吗?

    不,WindowsLiveID不是OpenID提供商.他们使用专有协议.自从他们的“测试版”期结束以来,他们从未宣布计划继续它.

  6. 如果我在代码中进行了更改,是否需要重新安装Windows服务?

    我写了一个Windows服务并安装它.现在我对代码进行了一些更改并重新构建了解决方案.我还应该重新安装服务吗?不,只需停止它,替换文件,然后重新启动它.

  7. 带有双引号的字符串回显使用Windows批处理输出文件

    我正在尝试使用Windows批处理文件重写配置文件.我循环遍历文件的行并查找我想要用指定的新行替换的行.我有一个’函数’将行写入文件问题是%Text%是一个嵌入双引号的字符串.然后失败了.可能还有其他角色也会导致失败.如何才能使用配置文件中的所有文本?尝试将所有“在文本中替换为^”.^是转义字符,因此“将被视为常规字符你可以尝试以下方法:其他可能导致错误的字符是:

  8. .net – 将控制台应用程序转换为服务?

    我正在寻找不同的优势/劣势,将我们长期使用的控制台应用程序转换为Windows服务.我们为ActiveMQ使用了一个叫做java服务包装器的东西,我相信人们告诉我你可以用它包装任何东西.这并不是说你应该用它包装任何东西;我们遇到了这个问题.控制台应用程序是一个.NET控制台应用程序,默认情况下会将大量信息记录到控制台,尽管这是可配置的.任何推荐?我们应该在VisualStudio中将其重建为服务吗?我使用“-install”/“-uninstall”开关执行此操作.例如,seehere.

  9. windows – 捕获外部程序的STDOUT和STDERR *同时*它正在执行(Ruby)

    哦,我在Windows上:-(实际上,它比我想象的要简单,这看起来很完美:…是的,它适用于Windows!

  10. windows – 当我试图批量打印变量时,为什么我得到“Echo is on”

    我想要执行一个简单的批处理文件脚本:当我在XP中运行时,它给了我预期的输出,但是当我在Vista或Windows7中运行它时,我在尝试打印值时得到“EchoisOn”.以下是程序的输出:摆脱集合表达式中的空格.等号(=)的两侧可以并且应该没有空格BTW:我通常在@echo关闭的情况下启动所有批处理文件,并以@echo结束它们,所以我可以避免将代码与批处理文件的输出混合.它只是使您的批处理文件输出更好,更清洁.

返回
顶部