PlikStream nie synchronizuje już przesunięcia pliku z systemem operacyjnym
Aby zwiększyć wydajność, FileStream nie synchronizuje już przesunięcia pliku z systemem operacyjnym.
Opis zmiany
W poprzednich wersjach FileStream platformy .NET synchronizuje przesunięcie pliku z systemem operacyjnym Windows podczas odczytu lub zapisu w pliku. Synchronizuje przesunięcie, wywołując metodę SetFilePointer, która jest kosztownym wywołaniem systemowym. Począwszy od platformy .NET 6, FileStream nie synchronizuje już przesunięcia pliku, a zamiast tego po prostu zachowuje przesunięcie w pamięci. FileStream.Position zawsze zwraca bieżące przesunięcie, ale jeśli uzyskasz dojście do pliku i FileStream.SafeFileHandle wykonasz zapytanie dotyczące systemu operacyjnego dla bieżącego przesunięcia pliku przy użyciu wywołania systemowego, wartość przesunięcia będzie wynosić 0.
Poniższy kod pokazuje, jak przesunięcie pliku różni się między poprzednimi wersjami platformy .NET i platformą .NET 6.
[DllImport("kernel32.dll")]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, out long lpNewFilePointer, uint dwMoveMethod);
byte[] bytes = new byte[10_000];
string path = Path.Combine(Path.GetTempPath(), Path.GetTempFileName());
using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.None, bufferSize: 4096, useAsync: true))
{
SafeFileHandle handle = fs.SafeFileHandle;
await fs.WriteAsync(bytes, 0, bytes.Length);
Console.WriteLine(fs.Position); // 10000 in all versions
if (SetFilePointerEx(handle, 0, out long currentOffset, 1 /* get current offset */))
{
Console.WriteLine(currentOffset); // 10000 in .NET 5, 0 in .NET 6
}
}
Wprowadzona wersja
.NET 6
Przyczyna wprowadzenia zmiany
Ta zmiana została wprowadzona w celu zwiększenia wydajności asynchronicznych odczytów i zapisów oraz rozwiązania następujących problemów:
- Win32 FileStream wyśmiewa wyszukiwanie dla każdego wywołania ReadAsync
- FileStream.Windows useAsync WriteAsync wywołuje blokujące interfejsy API
Dzięki tej zmianie ReadAsync operacje są do dwóch razy szybsze, a WriteAsync operacje są maksymalnie pięć razy szybsze.
Zalecana akcja
Zmodyfikuj dowolny kod, który polegał na synchronizowaniu przesunięcia.
Aby włączyć zachowanie platformy .NET 5 na platformie .NET 6, określ
AppContext
przełącznik lub zmienną środowiskową. Ustawiając przełącznik natrue
, zrezygnujesz ze wszystkich ulepszeń wydajności wFileStream
programie .NET 6.{ "configProperties": { "System.IO.UseNet5CompatFileStream": true } }
set DOTNET_SYSTEM_IO_USENET5COMPATFILESTREAM=1
Uwaga
Ten przełącznik jest dostępny tylko na platformie .NET 6. Został on usunięty na platformie .NET 7.
Dotyczy interfejsów API
Brak.