Bagikan melalui


Mengoptimalkan akses file

Buat aplikasi Platform Windows Universal (UWP) yang mengakses sistem file secara efisien, menghindari masalah performa karena latensi disk dan siklus memori/CPU.

Saat Anda ingin mengakses kumpulan file yang besar dan Anda ingin mengakses nilai properti selain properti Nama, FileType, dan Jalur umum, akses dengan membuat QueryOptions dan memanggil SetPropertyPrefetch. Metode SetPropertyPrefetch dapat secara dramatis meningkatkan performa aplikasi yang menampilkan kumpulan item yang diperoleh dari sistem file, seperti kumpulan gambar. Kumpulan contoh berikutnya menunjukkan beberapa cara untuk mengakses beberapa file.

Contoh pertama menggunakan Windows.Storage.StorageFolder.GetFilesAsync untuk mengambil info nama untuk sekumpulan file. Pendekatan ini memberikan performa yang baik, karena contohnya hanya mengakses properti nama.

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;
}
Dim library As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
Dim files As IReadOnlyList(Of StorageFile) =
    Await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate)

For i As Integer = 0 To files.Count - 1
    ' do something with the name of each file
    Dim fileName As String = files(i).Name
Next i

Contoh kedua menggunakan Windows.Storage.StorageFolder.GetFilesAsync lalu mengambil properti gambar untuk setiap file. Pendekatan ini memberikan performa yang buruk.

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;
}
Dim library As StorageFolder = Windows.Storage.KnownFolders.PicturesLibrary
Dim files As IReadOnlyList(Of StorageFile) = Await library.GetFilesAsync(Windows.Storage.Search.CommonFileQuery.OrderByDate)
For i As Integer = 0 To files.Count - 1
    Dim imgProps As ImageProperties =
        Await files(i).Properties.GetImagePropertiesAsync()

    ' do something with the date the image was taken
    Dim dateTaken As DateTimeOffset = imgProps.DateTaken
Next i

Contoh ketiga menggunakan QueryOptions untuk mendapatkan info tentang sekumpulan file. Pendekatan ini memberikan performa yang jauh lebih baik daripada contoh sebelumnya.

// 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/Set extra properties here
    var systemSize = propertyResults["System.Size"];
}
' Set QueryOptions to prefetch our specific properties
Dim queryOptions = New Windows.Storage.Search.QueryOptions(CommonFileQuery.OrderByDate, Nothing)
queryOptions.SetThumbnailPrefetch(ThumbnailMode.PicturesView,
            100, Windows.Storage.FileProperties.ThumbnailOptions.ReturnOnlyIfCached)
queryOptions.SetPropertyPrefetch(PropertyPrefetchOptions.ImageProperties,
                                 New String() {"System.Size"})

Dim queryResults As StorageFileQueryResult = KnownFolders.PicturesLibrary.CreateFileQueryWithOptions(queryOptions)
Dim files As IReadOnlyList(Of StorageFile) = Await queryResults.GetFilesAsync()


For Each file In files
    Dim imageProperties As ImageProperties = Await file.Properties.GetImagePropertiesAsync()

    ' Do something with the date the image was taken.
    Dim dateTaken As DateTimeOffset = imageProperties.DateTaken

    ' Performance gains increase with the number of properties that are accessed.
    Dim propertyResults As IDictionary(Of String, Object) =
        Await file.Properties.RetrievePropertiesAsync(New String() {"System.Size"})

    ' Get/Set extra properties here
    Dim systemSize = propertyResults("System.Size")

Next file

Jika Anda melakukan beberapa operasi pada objek Windows.Storage seperti Windows.Storage.ApplicationData.Current.LocalFolder, buat variabel lokal untuk mereferensikan sumber penyimpanan tersebut sehingga Anda tidak membuat ulang objek perantara setiap kali Anda mengaksesnya.

Performa streaming di C# dan Visual Basic

Buffering antara aliran UWP dan .NET

Ada banyak skenario ketika Anda mungkin ingin mengonversi aliran UWP (seperti Windows.Storage.Streams.IInputStream atau IOutputStream) ke aliran .NET (System.IO.Stream). Misalnya, ini berguna ketika Anda menulis aplikasi UWP dan ingin menggunakan kode .NET yang ada yang berfungsi pada aliran dengan sistem file UWP. Untuk mengaktifkan ini, API .NET untuk aplikasi UWP menyediakan metode ekstensi yang memungkinkan Anda mengonversi antara jenis aliran .NET dan UWP. Untuk informasi selengkapnya, lihat WindowsRuntimeStreamExtensions.

Saat Mengonversi aliran UWP ke aliran .NET, Anda secara efektif membuat adaptor untuk aliran UWP yang mendasar. Dalam beberapa keadaan, ada biaya runtime yang terkait dengan metode pemanggilan pada aliran UWP. Ini dapat memengaruhi kecepatan aplikasi Anda, terutama dalam skenario di mana Anda melakukan banyak operasi baca atau tulis yang kecil, sering.

Untuk mempercepat aplikasi, adaptor aliran UWP berisi buffer data. Sampel kode berikut menunjukkan bacaan berturut-turut kecil menggunakan adaptor aliran UWP dengan ukuran buffer default.

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);
}
Dim file As StorageFile = Await Windows.Storage.ApplicationData.Current -
.LocalFolder.GetFileAsync("example.txt")
Dim windowsRuntimeStream As Windows.Storage.Streams.IInputStream =
    Await file.OpenReadAsync()

Dim destinationArray() As Byte = New Byte(8) {}

' Create an adapter with the default buffer size.
Dim managedStream As Stream = windowsRuntimeStream.AsStreamForRead()
Using (managedStream)

    ' 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)

End Using

Perilaku buffering default ini diinginkan dalam sebagian besar skenario di mana Anda mengonversi aliran UWP ke aliran .NET. Namun, dalam beberapa skenario Anda mungkin ingin mengubah perilaku buffering untuk meningkatkan performa.

Bekerja dengan himpunan data besar

Saat membaca atau menulis kumpulan data yang lebih besar, Anda mungkin dapat meningkatkan throughput baca atau tulis dengan memberikan ukuran buffer besar ke metode ekstensi AsStreamForRead, AsStreamForWrite, dan AsStream. Ini memberi adaptor aliran ukuran buffer internal yang lebih besar. Misalnya, saat meneruskan aliran yang berasal dari file besar ke pengurai XML, pengurai dapat membuat banyak bacaan kecil berurutan dari aliran. Buffer besar dapat mengurangi jumlah panggilan ke aliran UWP yang mendasar dan meningkatkan performa.

Catatan Anda harus berhati-hati saat mengatur ukuran buffer yang lebih besar dari sekitar 80 KB, karena ini dapat menyebabkan fragmentasi pada tumpukan pengumpul sampah (lihat Meningkatkan performa pengumpulan sampah). Contoh kode berikut membuat adaptor aliran terkelola dengan buffer 81.920 byte.

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

Metode Stream.CopyTo dan CopyToAsync juga mengalokasikan buffer lokal untuk menyalin antar aliran. Seperti halnya metode ekstensi AsStreamForRead , Anda mungkin bisa mendapatkan performa yang lebih baik untuk salinan aliran besar dengan mengambil alih ukuran buffer default. Contoh kode berikut menunjukkan perubahan ukuran buffer default panggilan 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);
Dim destination As MemoryStream = 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)

Contoh ini menggunakan ukuran buffer 1 MB, yang lebih besar dari 80 KB yang sebelumnya direkomendasikan. Menggunakan buffer besar seperti itu dapat meningkatkan throughput operasi penyalinan untuk himpunan data yang sangat besar (yaitu, beberapa ratus megabyte). Namun, buffer ini dialokasikan pada tumpukan objek besar dan berpotensi menurunkan performa pengumpulan sampah. Anda hanya boleh menggunakan ukuran buffer besar jika akan terlihat meningkatkan performa aplikasi Anda.

Ketika Anda bekerja dengan sejumlah besar aliran secara bersamaan, Anda mungkin ingin mengurangi atau menghilangkan overhead memori buffer. Anda dapat menentukan buffer yang lebih kecil, atau mengatur parameter bufferSize ke 0 untuk menonaktifkan buffering sepenuhnya untuk adaptor aliran tersebut. Anda masih dapat mencapai performa throughput yang baik tanpa buffering jika Anda melakukan pembacaan dan penulisan besar ke aliran terkelola.

Melakukan operasi peka latensi

Anda mungkin juga ingin menghindari buffering jika Anda ingin latensi rendah membaca dan menulis dan tidak ingin membaca dalam blok besar dari aliran UWP yang mendasarinya. Misalnya, Anda mungkin ingin latensi rendah membaca dan menulis jika Anda menggunakan aliran untuk komunikasi jaringan.

Di aplikasi obrolan, Anda dapat menggunakan streaming melalui antarmuka jaringan untuk mengirim pesan bolak-balik. Dalam hal ini Anda ingin mengirim pesan segera setelah siap dan tidak menunggu buffer terisi. Jika Anda mengatur ukuran buffer ke 0 saat memanggil metode ekstensi AsStreamForRead, AsStreamForWrite, dan AsStream, maka adaptor yang dihasilkan tidak akan mengalokasikan buffer, dan semua panggilan akan memanipulasi aliran UWP yang mendasar secara langsung.