Aracılığıyla paylaş


Dosya erişimini iyileştirme

Disk gecikme süresi ve bellek/CPU döngüleri nedeniyle performans sorunlarını önleyerek dosya sistemine verimli bir şekilde erişen Evrensel Windows Platformu (UWP) uygulamaları oluşturun.

Büyük bir dosya koleksiyonuna erişmek ve tipik Name, FileType ve Path özellikleri dışındaki özellik değerlerine erişmek istediğinizde, QueryOptions oluşturup SetPropertyPrefetchçağırarak bunlara erişin. SetPropertyPrefetch yöntemi, görüntü koleksiyonu gibi dosya sisteminden alınan bir öğe koleksiyonunu görüntüleyen uygulamaların performansını önemli ölçüde artırabilir. Sonraki örnek kümesinde birden çok dosyaya erişmenin birkaç yolu gösterilmektedir.

İlk örnekte, bir dosya kümesinin ad bilgilerini almak için Windows.Storage.StorageFolder.GetFilesAsync kullanılır. Örnek yalnızca name özelliğine eriştiğinden bu yaklaşım iyi bir performans sağlar.

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

İkinci örnek, Windows.Storage.StorageFolder.GetFilesAsync kullanır ve her dosyanın görüntü özelliklerini alır. Bu yaklaşım düşük performans sağlar.

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

Üçüncü örnek, bir dosya kümesi hakkında bilgi almak için QueryOptions kullanır. Bu yaklaşım önceki örnekten çok daha iyi performans sağlar.

// 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

Windows.Storage.ApplicationData.Current.LocalFoldergibi Windows.Storage nesnelerinde birden çok işlem gerçekleştiriyorsanız, ara nesneleri her erişişinde yeniden oluşturmamak için bu depolama kaynağına başvurmak için yerel bir değişken oluşturun.

C# ve Visual Basic'te akış performansı

UWP ve .NET akışları arasında tamponlama

Bir UWP akışını (Windows.Storage.Streams.IInputStream veya IOutputStream) bir .NET akışına (System.IO.Stream) dönüştürmek isteyebileceğiniz birçok senaryo vardır. Örneğin, bir UWP uygulaması yazarken ve UWP dosya sistemiyle akışlarda çalışan mevcut .NET kodunu kullanmak istediğinizde bu yararlı olur. Bunu etkinleştirmek için, UWP uygulamaları için .NET API'leri .NET ve UWP akış türleri arasında dönüştürmenizi sağlayan uzantı yöntemleri sağlar. Daha fazla bilgi için bkz. WindowsRuntimeStreamExtensions.

UWP akışını .NET akışına dönüştürdüğünüzde, temel alınan UWP akışı için etkili bir şekilde bir bağdaştırıcı oluşturursunuz. Bazı durumlarda, UWP akışlarında çağırma yöntemleriyle ilişkili bir çalışma zamanı maliyeti vardır. Bu, özellikle de çok sayıda küçük, sık okuma veya yazma işlemi gerçekleştirdiğiniz senaryolarda uygulamanızın hızını etkileyebilir.

Uygulamaları hızlandırmak için UWP akış bağdaştırıcıları bir veri arabelleği içerir. Aşağıdaki kod örneği, varsayılan arabellek boyutuna sahip bir UWP akış bağdaştırıcısı kullanılarak yapılan küçük ardışık okumaları gösterir.

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

Bu varsayılan arabelleğe alma davranışı, UWP akışını .NET akışına dönüştürdüğünüz çoğu senaryoda tercih edilir. Ancak bazı senaryolarda performansı artırmak için tamponlama davranışını değiştirmek isteyebilirsiniz.

Büyük veri kümeleriyle çalışma

Daha büyük veri kümeleri okurken veya yazarken, AsStreamForRead, AsStreamForWriteve AsStream uzantı yöntemlerine büyük bir arabellek boyutu sağlayarak okuma veya yazma aktarım hızınızı artırabilirsiniz. Bu, akış adaptörüne daha büyük bir iç arabellek boyutu verir. Örneğin, büyük bir dosyadan gelen bir akışı XML ayrıştırıcısına geçirirken, ayrıştırıcı akıştan birçok sıralı küçük okuma yapabilir. Büyük bir arabellek, temel alınan UWP akışına yapılan çağrı sayısını azaltabilir ve performansı artırabilir.

Not Çöp toplayıcı yığınında parçalanmalara neden olabileceğinden yaklaşık 80 KB'tan büyük bir arabellek boyutu ayarlarken dikkatli olmanız gerekir (bkz. Çöp toplama performansını iyileştirme). Aşağıdaki kod örneği, 81.920 baytlık arabelleğe sahip bir yönetilen akış bağdaştırıcısı oluşturur.

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

Stream.CopyTo ve CopyToAsync yöntemleri, akışlar arasında kopyalama yapmak için yerel bir arabellek de ayırır. AsStreamForRead uzantısı yönteminde olduğu gibi, varsayılan arabellek boyutunu geçersiz kılarak büyük akış kopyaları için daha iyi performans elde edebilirsiniz. Aşağıdaki kod örneği, CopyToAsync çağrısının varsayılan arabellek boyutunu değiştirmeyi gösterir.

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)

Bu örnekte, daha önce önerilen 80 KB'tan büyük olan 1 MB arabellek boyutu kullanılır. Böyle büyük bir arabellek kullanmak, çok büyük veri kümeleri (yani birkaç yüz megabayt) için kopyalama işleminin aktarım hızını iyileştirebilir. Ancak, bu arabellek büyük nesne yığınında tahsis edilir ve çöp toplama performansını potansiyel olarak düşürebilir. Büyük arabellek boyutlarını yalnızca uygulamanızın performansını önemli ölçüde artıracaksa kullanmanız gerekir.

Aynı anda çok sayıda akışla çalışırken, bellek tamponu fazlalığını azaltmak veya ortadan kaldırmak isteyebilirsiniz. Daha küçük bir arabellek belirtebilir veya bufferSize parametresini 0 olarak ayarlayarak bu akış bağdaştırıcısı için arabelleğe almayı tamamen kapatabilirsiniz. Yönetilen akışta büyük okuma ve yazma işlemleri gerçekleştiriyorsanız arabelleğe almadan da iyi aktarım hızı performansı elde edebilirsiniz.

Gecikme süresine duyarlı işlemler gerçekleştirme

Ayrıca, düşük gecikme süreli okuma ve yazma işlemleri yapmak ve temel alınan UWP akışının büyük bloklarında okumak istemiyorsanız arabelleğe almayı önlemek isteyebilirsiniz. Örneğin, akışı ağ iletişimleri için kullanıyorsanız düşük gecikme süreli okuma ve yazma işlemleri isteyebilirsiniz.

Bir sohbet uygulamasında, iletileri ileri geri göndermek için ağ arabirimi üzerinden bir akış kullanabilirsiniz. Bu durumda, iletileri hazır oldukları anda göndermek ve arabelleğin dolmasını beklememek istiyorsunuz. AsStreamForRead, AsStreamForWriteve AsStream uzantı yöntemlerini çağırırken arabellek boyutunu 0 olarak ayarlarsanız, sonuçta elde edilen bağdaştırıcı bir arabellek ayırmaz ve tüm çağrılar, temel alınan UWP akışını doğrudan denetler.