Metode terbaik untuk menangani masalah ini adalah dengan menggunakan SetSystemFileCacheSize
API sebagai MS KB976618 memerintahkan digunakan untuk menginstruksikan .
Jangan menghapus cache secara berkala
Menggunakan SetSystemFileCacheSize
fungsi daripada membersihkan cache secara berkala meningkatkan kinerja dan stabilitas. Menghapus cache secara berkala akan menghasilkan metafile yang terlalu banyak dan info lainnya dihapus dari memori, dan Windows harus membaca kembali informasi yang diperlukan kembali ke dalam RAM dari HDD. Ini menciptakan penurunan kinerja yang tiba-tiba dan parah selama beberapa detik setiap kali Anda membersihkan cache, diikuti oleh kinerja yang baik yang perlahan-lahan menurun saat memori dipenuhi dengan data metafile.
Menggunakan SetSystemFileCacheSize
fungsi ini menetapkan minimum dan maksimum yang akan menghasilkan Windows menandai data metafile lama yang berlebih sebagai memori siaga yang dapat digunakan atau dibuang oleh fungsi cache yang normal sesuai dengan tuntutan sumber daya saat ini dan prioritas cache yang normal. Ini juga memungkinkan lebih banyak data metafile daripada maksimum memori aktif yang Anda atur, berada di memori sebagai data siaga jika Windows tidak menggunakan memori untuk hal lain, sambil mempertahankan banyak memori yang tersedia. Ini adalah situasi yang ideal menjaga karakteristik kinerja sistem baik setiap saat.
Program Pihak Ketiga Tidak Didukung oleh MS
Jika Anda seperti saya dan tidak ingin menjalankan biner dari pihak ketiga yang tidak dikenal di server produksi Anda, Anda ingin alat MS resmi atau beberapa kode yang dapat Anda periksa sebelum berjalan di server tersebut. Alat DynCache untuk 2008 R2 secara praktis tidak mungkin diperoleh dari M $ tanpa membayar untuk kasus dukungan dan terus terang, berdasarkan kode untuk 2008, tampaknya terlalu membengkak untuk tugas karena Windows sudah memiliki logika bawaan yang diperlukan untuk ukuran secara dinamis cache — itu hanya perlu tahu maksimum yang sesuai untuk sistem Anda.
Solusi untuk semua hal di atas
Saya menulis naskah Powershell yang bekerja pada mesin 64 bit. Anda harus menjalankannya sebagai administrator dengan hak yang lebih tinggi. Anda harus dapat menjalankannya, seperti pada x64 windows Vista / Server 2008 hingga dan termasuk 10 / Server 2012 R2 dengan jumlah RAM berapa pun. Anda tidak perlu menginstal perangkat lunak tambahan apa pun, dan akibatnya menjaga server / workstation Anda sepenuhnya didukung oleh MS.
Anda harus menjalankan skrip ini di setiap boot dengan hak istimewa yang ditinggikan untuk pengaturan menjadi permanen. Penjadwal Tugas Windows dapat melakukan ini untuk Anda. Jika instalasi Windows berada di dalam mesin virtual dan Anda mengubah jumlah RAM yang dialokasikan untuk VM itu, Anda juga harus menjalankannya setelah perubahan.
Anda dapat menjalankan skrip ini kapan saja pada sistem yang sedang berjalan bahkan saat digunakan dalam produksi tanpa harus me-reboot sistem atau mematikan layanan apa pun.
# 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", SetLastError = true, 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, IntPtr MaximumFileCacheSize, 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", ExactSpelling = true, 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, 0, 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]$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
Ada garis di dekat bagian atas yang mengatakan $MaxPercent = 12.5
bahwa set set kerja maksimum baru (memori aktif) menjadi 12,5% dari total RAM fisik. Windows akan secara dinamis mengukur jumlah data metafile dalam memori aktif berdasarkan permintaan sistem, jadi Anda tidak perlu menyesuaikan secara maksimal ini secara dinamis.
Ini tidak akan memperbaiki masalah apa pun yang Anda miliki dengan cache file yang dipetakan menjadi terlalu besar.
Saya juga membuat GetSystemFileCacheSize
skrip Powershell dan mempostingnya di StackOverflow .
Sunting: Saya juga harus menunjukkan bahwa Anda tidak boleh menjalankan salah satu dari kedua skrip ini dari instance Powershell yang sama lebih dari sekali, atau Anda akan menerima kesalahan bahwa Add-Type
panggilan telah dilakukan.
Sunting: SetSystemFileCacheSize
skrip yang diperbarui ke versi 1.1 yang menghitung nilai cache maks yang sesuai untuk Anda dan memiliki tata letak keluaran status yang lebih bagus.
Sunting: Sekarang saya telah memutakhirkan laptop Windows 7 saya, saya dapat memberi tahu Anda bahwa skrip berjalan dengan sukses di Windows 10, meskipun saya belum menguji apakah masih diperlukan. Tetapi sistem saya masih stabil bahkan ketika memindahkan file HDD mesin virtual.