Optimalizace přístupu k souborům

Vytvářejte aplikace WinUI pomocí sady Windows App SDK, které efektivně přistupují k systému souborů, a vyhněte se problémům s výkonem způsobeným latencí disku a zbytečným využitím paměti nebo procesoru.

Pokud chcete získat přístup k velké kolekci souborů a chcete získat přístup k hodnotám vlastností kromě typických vlastností Name, FileType a Path, získejte k nim přístup vytvořením QueryOptions a voláním SetPropertyPrefetch. Metoda SetPropertyPrefetch může výrazně zlepšit výkon aplikací, které zobrazují kolekci položek získaných ze systému souborů, jako je například kolekce obrázků. Další sada příkladů ukazuje několik způsobů přístupu k více souborům.

První příklad používá Windows.Storage.StorageFolder.GetFilesAsync k načtení informací o názvu sady souborů. Tento přístup poskytuje dobrý výkon, protože příklad přistupuje pouze k vlastnosti name.

StorageFolder library = Windows.Storage.KnownFolders.PicturesLibrary;
IReadOnlyList<StorageFile> files = await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate);

for (int i = 0; i < files.Count; i++)
{
    // Do something with the name of each file.
    string fileName = files[i].Name;
}

Druhý příklad používá Windows.Storage.StorageFolder.GetFilesAsync a pak načte vlastnosti obrázku pro každý soubor. Tento přístup poskytuje nízký výkon.

StorageFolder library = Windows.Storage.KnownFolders.PicturesLibrary;
IReadOnlyList<StorageFile> files = await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate);
for (int i = 0; i < files.Count; i++)
{
    ImageProperties imgProps = await files[i].Properties.GetImagePropertiesAsync();

    // Do something with the date the image was taken.
    DateTimeOffset date = imgProps.DateTaken;
}

Třetí příklad používá QueryOptions k získání informací o sadě souborů. Tento přístup poskytuje mnohem lepší výkon než předchozí příklad.

// Set QueryOptions to prefetch our specific properties.
var queryOptions = new Windows.Storage.Search.QueryOptions(CommonFileQuery.OrderByDate, null);
queryOptions.SetThumbnailPrefetch(
    ThumbnailMode.PicturesView,
    100,
    ThumbnailOptions.ReturnOnlyIfCached);
queryOptions.SetPropertyPrefetch(
    PropertyPrefetchOptions.ImageProperties,
    new string[] { "System.Size" });

StorageFileQueryResult queryResults = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions);
IReadOnlyList<StorageFile> files = await queryResults.GetFilesAsync();

foreach (var file in files)
{
    ImageProperties imageProperties = await file.Properties.GetImagePropertiesAsync();

    // Do something with the date the image was taken.
    DateTimeOffset dateTaken = imageProperties.DateTaken;

    // Performance gains increase with the number of properties that are accessed.
    IDictionary<string, object> propertyResults =
        await file.Properties.RetrievePropertiesAsync(new string[] { "System.Size" });

    // Get or set extra properties here.
    var systemSize = propertyResults["System.Size"];
}

Pokud provádíte více operací s objekty Windows.Storage, jako Windows.Storage.ApplicationData.Current.LocalFolderje například , vytvořte místní proměnnou, která bude odkazovat na tento zdroj úložiště, takže při každém přístupu k němu nebudete znovu vytvářet zprostředkující objekty.

Výkon streamu v jazyce C#

Ukládání do vyrovnávací paměti mezi streamy Windows Runtime a .NET

Existuje mnoho scénářů, kdy můžete chtít převést stream prostředí Windows Runtime (například Windows.Storage.Streams.IInputStream nebo IOutputStream) na stream .NET (System.IO.Stream). To je užitečné například při psaní aplikace WinUI a chcete použít existující kód .NET, který funguje na datových proudech s rozhraními API služby Windows Storage. Pro povolení této možnosti poskytuje .NET rozšiřující metody, které umožňují převést mezi typy datových proudů .NET a Windows Runtime. Další informace najdete v tématu WindowsRuntimeStreamExtensions.

Při převodu datového proudu prostředí Windows Runtime na datový proud .NET efektivně vytvoříte adaptér pro podkladový datový proud prostředí Windows Runtime. Za určitých okolností existují náklady za běhu spojené s vyvoláním metod ve streamech windows Runtime. To může mít vliv na rychlost aplikace, zejména ve scénářích, kdy provádíte mnoho malých, častých operací čtení nebo zápisu.

Adaptéry datového proudu prostředí Windows Runtime, které pomáhají zrychlit aplikace, obsahují datovou vyrovnávací paměť. Následující ukázka kódu demonstruje malé po sobě jdoucí čtení dat s použitím streamového adaptéru Windows Runtime s výchozí velikostí vyrovnávací paměti.

StorageFile file = await Windows.Storage.ApplicationData.Current
    .LocalFolder.GetFileAsync("example.txt");
Windows.Storage.Streams.IInputStream windowsRuntimeStream =
    await file.OpenReadAsync();

byte[] destinationArray = new byte[8];

// Create an adapter with the default buffer size.
using (var managedStream = windowsRuntimeStream.AsStreamForRead())
{
    // Read 8 bytes into destinationArray.
    // A larger block is actually read from the underlying
    // windowsRuntimeStream and buffered within the adapter.
    await managedStream.ReadAsync(destinationArray, 0, 8);

    // Read 8 more bytes into destinationArray.
    // This call may complete much faster than the first call
    // because the data is buffered and no call to the
    // underlying windowsRuntimeStream needs to be made.
    await managedStream.ReadAsync(destinationArray, 0, 8);
}

Toto výchozí chování ukládání do vyrovnávací paměti je žádoucí ve většině scénářů, kdy převedete datový proud prostředí Windows Runtime na datový proud .NET. V některých scénářích můžete chtít ale upravit chování vyrovnávací paměti, aby se zvýšil výkon.

Práce s velkými datovými sadami

Při čtení nebo zápisu větších sad dat můžete zvýšit propustnost čtení nebo zápisu tím, že poskytnete velkou velikost vyrovnávací paměti metodám rozšíření AsStreamForRead, AsStreamForWrite a AsStream . Adaptér datového proudu tak má větší velikost interní vyrovnávací paměti. Například při předávání datového proudu, který pochází z velkého souboru do analyzátoru XML, může analyzátor provádět mnoho sekvenčních malých čtení z datového proudu. Velká vyrovnávací paměť může snížit počet volání základního datového proudu prostředí Windows Runtime a zvýšit výkon.

Poznámka:

Při nastavování velikosti vyrovnávací paměti, která je větší než přibližně 80 kB, buďte opatrní, protože to může způsobit fragmentaci haldy garbage collectoru. Pokud potřebujete další pokyny, podívejte se na Zlepšení výkonu uvolňování paměti v aplikacích WinUI. Následující příklad kódu vytvoří adaptér spravovaného datového proudu s vyrovnávací pamětí 81 920 bajtů.

// Create a stream adapter with an 80 KB buffer.
Stream managedStream = nativeStream.AsStreamForRead(bufferSize: 81920);

Metody Stream.CopyTo a CopyToAsync také přidělují místní vyrovnávací paměť pro kopírování mezi datovými proudy. Stejně jako u metody rozšíření AsStreamForRead můžete být schopni získat lepší výkon pro velké kopie datového proudu přepsáním výchozí velikosti vyrovnávací paměti. Následující příklad kódu ukazuje změnu výchozí velikosti vyrovnávací paměti u volání CopyToAsync.

MemoryStream destination = new MemoryStream();

// Copies the buffer into memory using the default copy buffer.
await managedStream.CopyToAsync(destination);

// Copy the buffer into memory using a 1 MB copy buffer.
await managedStream.CopyToAsync(destination, bufferSize: 1024 * 1024);

Tento příklad používá velikost vyrovnávací paměti 1 MB, která je větší než 80 kB dříve doporučená. Použití takové velké vyrovnávací paměti může zlepšit propustnost operace kopírování pro velmi velké datové sady (to znamená několik stovek megabajtů). Tato vyrovnávací paměť je však přidělena na haldu velkého objektu a může potenciálně degradovat výkon správy paměti. Velké velikosti vyrovnávací paměti byste měli používat jenom v případě, že výrazně zlepší výkon vaší aplikace.

Při práci s velkým počtem datových proudů současně můžete chtít snížit nebo eliminovat nadbytečné paměťové zatížení vyrovnávací paměti. Můžete zadat menší vyrovnávací paměť nebo nastavit parametr bufferSize na hodnotu 0, aby se pro tento adaptér datového proudu úplně vypnulo ukládání do vyrovnávací paměti. Pokud provádíte velké čtení a zápisy do spravovaného datového proudu, můžete i tak dosáhnout dobrého výkonu propustnosti bez ukládání do vyrovnávací paměti.

Provádění operací citlivých na latenci

Můžete se také vyhnout ukládání do vyrovnávací paměti, pokud chcete čtení a zápisy s nízkou latencí a nechcete číst ve velkých blocích ze základního datového proudu prostředí Windows Runtime. Pokud například používáte datový proud pro síťovou komunikaci, můžete chtít čtení a zápisy s nízkou latencí.

V chatovací aplikaci můžete použít stream přes síťové rozhraní k odesílání zpráv tam a zpět. V takovém případě chcete odesílat zprávy hned, jak jsou připravené, a nečekat na vyplnění vyrovnávací paměti. Pokud při volání metod rozšíření AsStreamForRead, AsStreamForWrite a AsStream nastavíte velikost vyrovnávací paměti na hodnotu 0, výsledný adaptér nepřidělí vyrovnávací paměť a všechna volání budou manipulovat s podkladovým streamem prostředí Windows Runtime přímo.