Effizientes Zugreifen auf das Dateisystem

Effizientes Zugreifen auf das Dateisystem (HTML)

[ Dieser Artikel richtet sich an Windows 8.x- und Windows Phone 8.x-Entwickler, die Windows-Runtime-Apps schreiben. Wenn Sie für Windows 10 entwickeln, finden Sie weitere Informationen unter neueste Dokumentation]

Die Dateisystem- und Mediendateien sind ein wichtiger Bestandteil der meisten Apps und zudem einer der häufigsten Gründe für Leistungsprobleme. Der Zugriff auf Mediendateien kann sehr aufwendig sein, da Arbeitsspeicher und CPU-Zyklen zum Speichern sowie zum Decodieren und Anzeigen der Medien benötigt werden. Hier erfahren Sie, wie Sie die Leistung Ihrer App beim Arbeiten mit Mediendateien steigern.

Verwenden von Miniaturbildern für das schnelle Rendern

Anstatt eine große Version eines Bilds für die Anzeige als Miniaturbild herunterzuskalieren, sollten Sie die Miniaturbild-APIs der Windows-Runtime verwenden. Das Herunterskalieren eines Bilds in Originalgröße ist ineffizient, da die App das Bild in Originalgröße zunächst lesen und decodieren muss. Für das anschließende Skalieren wird weitere Zeit benötigt. Die Windows-Runtime stellt eine Reihe von APIs bereit, die von einem effizienten Cache unterstützt werden. Diese ermöglichen das Abrufen einer kleineren Version eines Bilds, das als Miniaturbild genutzt werden kann. Mithilfe dieser APIs kann die Zeit für die Codeausführung um einige Sekunden reduziert und die visuelle Qualität der Miniaturansicht verbessert werden. Da diese APIs die Miniaturansichten zwischenspeichern, können sie nachfolgende Startvorgänge der App beschleunigen.

In diesem Beispiel wird der Benutzer aufgefordert, ein Bild anzugeben, das anschließend angezeigt wird.


// Pick an image file
picker.pickSingleFileAsync()
.then(function (file) {
  var imgTag = document.getElementById("imageTag");
  imgTag.src = URL.createObjectURL(file, false);
});


Das vorige Beispiel funktioniert, wenn ein Bild in Originalgröße (oder annähernder Originalgröße) gerendert werden soll. Es ist jedoch ineffizient, wenn eine Miniaturbildansicht des Bilds dargestellt werden soll. Die Miniaturbild-APIs geben eine Miniaturbildversion des Bilds zurück, die von der App sehr viel schneller als das Bild in Originalgröße decodiert und angezeigt werden kann. Im nächsten Beispiel wird das Bild mithilfe der getThumbnailAsync-Methode abgerufen, und ein auf dem Bild basierendes Miniaturbild wird erstellt.


// Pick an image file
picker.pickSingleFileAsync()
.then(function (file) {
  var properties = Windows.Storage.FileProperties.ThumbnailMode;
  return file.getThumbnailAsync(properties.singleItem, 1024);
})
.then(function (thumb) {
  var imgTag = document.getElementById("imageTag");
  imgTag.src = URL.createObjectURL(thumb, false);
});



Verwenden der richtigen Miniaturansichtgröße

Das System speichert die Miniaturansichten in verschiedenen Größen zwischen. Um die Leistung und Bildqualität zu verbessern, sollten Sie Miniaturansichten in einer der zwischengespeicherten Größen anzeigen, damit die App die Miniaturansichtgröße nicht ändern muss. Für den Miniaturansichtmodus SingleItem und PicturesView sind folgende Miniaturansichtgrößen (in Pixel) verfügbar:

Batchanforderungen für Lesevorgänge mehrerer Dateieigenschaften

Wenn Sie auf eine große Collection und auf andere Eigenschaftenwerte als die typischen Eigenschaften name, fileType und path zugreifen möchten, empfiehlt sich ein Zugriff über die Windows.Storage.BulkAccess-APIs. Mithilfe von Windows.Storage.BulkAccess kann die Lesezeit beim Verarbeiten vieler Dateien um einige hundert Millisekunden reduziert werden.

Die Windows.Storage.BulkAccess-APIs kombinieren mehrere Dateivorgänge in einem einzigen Vorgang, wodurch schneller auf mehrere Dateien und Dateieigenschaften zugegriffen werden kann. Mit den Windows.Storage.BulkAccess-APIs kann die Leistung von Apps wesentlich gesteigert werden, in denen eine Sammlung von aus dem Dateisystem abgerufenen Elementen angezeigt wird (z. B. eine Sammlung von Bildern).

In den nächsten Beispielen werden einige Möglichkeiten veranschaulicht, auf mehrere Dateien zuzugreifen.

Im ersten Beispiel werden mithilfe von Windows.Storage.StorageFolder.getFilesAsync die Namensinformationen für eine Gruppe von Dateien abgerufen. Dieser Ansatz sichert eine gute Leistung, da im Beispiel lediglich auf die name-Eigenschaft zugegriffen wird.


var library = Windows.Storage.KnownFolders.picturesLibrary;
library.getFilesAsync(Windows.Storage.Search.CommonFileQuery.orderByDate, start, page)
.then(function (files) {
    var count = files.length;
    for (var i = 0; i < count; i++) {
        // The name property comes with every file
        console.log(files[i].name);
    }
});



Im zweiten Beispiel wird Windows.Storage.StorageFolder.getFilesAsync verwendet, und anschließend werden die Bildeigenschaften für die einzelnen Dateien abgerufen. Bei dieser Vorgehensweise ist eine schlechte Leistung zu beobachten.



// Do not use: inefficient code. 
var library = Windows.Storage.KnownFolders.picturesLibrary;
library.getFilesAsync(Windows.Storage.Search.CommonFileQuery.orderByDate, start, page)
.then(function (files) {
    var count = files.length;
    for (var i = 0; i < count; i++) {
        // The dateTaken property is image specific and needs to be specially requested
        files[i].properties.getImagePropertiesAsync().then(function (props) {
            console.log(file.name + " - " + props.dateTaken);
        });
    });
});




Im dritten Beispiel werden mit Windows.Storage.BulkAccess.FileInformationFactory.getFilesAsync Informationen zu Bildeigenschaften für eine Gruppe von Dateien abgerufen. Diese Vorgehensweise bietet eine wesentlich bessere Leistung als das vorhergehende Beispiel.


var library = Windows.Storage.KnownFolders.picturesLibrary;
var query = library.createFileQuery(Windows.Storage.Search.CommonFileQuery.orderByDate);
var delayLoad = true; // Depends on if/when/how fast you want your thumbnails
var access = new Windows.Storage.BulkAccess.FileInformationFactory(
    query, Windows.Storage.FileProperties.ThumbnailMode.picturesView,
    Math.max(app.settings.itemHeight, app.settings.itemWidth),
    Windows.Storage.FileProperties.ThumbnailOptions.returnOnlyIfCached,
    delayLoad);
access.getFilesAsync(start, page).then(function (files) {
    var count = files.length;
    for (var i = 0; i < count; i++) {
        console.log(files[i].name + " - " + files[i].imageProperties.dateTaken);
        // The more 'extra' properties you're accessing, the better the perf gains
    }
});



Wenn Sie mehrere Vorgänge an Windows.Storage-Objekten wie Windows.Storage.ApplicationData.Current.LocalFolder ausführen, erstellen Sie eine lokale Variable, die auf die Speicherquelle verweist, sodass nicht bei jedem Zugriff erneut Zwischenobjekte erstellt werden müssen.

Vermeiden Sie das Lesen von Dateien beim Starten der App, da dies ein speicherintensiver Vorgang ist. Listen Sie stattdessen die Bibliothek nach dem Starten der App auf. Sie könnten die Ergebnisse auch zwischenspeichern, wenn sie für jeden Start erforderlich sind.

Freigeben von Medien und Datenströmen nach Abschluss des Vorgangs

Mediendateien sind die gängigsten und aufwendigsten Ressourcen, die von Apps genutzt werden. Da Mediendateien den Speicherbedarf Ihrer App beträchtlich steigern können, ist es unerlässlich, das Handle zu den Medien unverzüglich freizugeben, sobald diese von der App nicht mehr verwendet werden. Durch das Freigegeben von nicht verwendeten Medienstreams kann der Arbeitsspeicherbedarf der App deutlich reduziert und vermieden werden, dass sie beendet wird, wenn sie angehalten wurde.

Wenn die App beispielsweise ein Blob verwendet, müssen Sie unbedingt URL.revokeObjectURL aufrufen, um die URL für das Blob zu widerrufen. Dadurch wird der Verweis auf den zugrunde liegenden Datenstrom freigegeben.

Wenn die App ein RandomAccessStream-Objekt oder ein IInputStream-Objekt verarbeitet, müssen Sie die close-Methode für das Objekt aufrufen, sobald dieses nicht mehr von der App verwendet wird. Dadurch wird das zugrunde liegende Objekt freigegeben.

Widerrufen aller mit URL.createObjectURL erstellten URLs, um einen Arbeitsspeicherverlust zu vermeiden

Eine gängige Methode zum Laden von Medien für ein audio-, video- oder img-Element besteht darin, mit der URL.createObjectURL-Methode eine URL zu erstellen, die verwendet werden kann. Bei Aufruf dieser Methode wird das System angewiesen, einen internen Verweis auf die betreffenden Medien beizubehalten (hierbei kann es sich um ein Blob, File oder StorageFile handeln). Das System streamt mithilfe dieses internen Verweises das Objekt in das entsprechende Element. Da dem System nicht bekannt ist, zu welchem Zeitpunkt die Daten benötigt werden, wird der interne Verweis so lange aufbewahrt, bis Sie das System anweisen, ihn freizugeben. Häufig werden versehentlich nicht benötigte interne Verweise beibehalten, wodurch große Mengen an Arbeitsspeicher gebunden werden.

Es gibt zwei Möglichkeiten, die Objekte freizugeben:

  • Sie können die URL explizit widerrufen, indem Sie die URL.revokeObjectURL-Methode aufrufen und an die URL übergeben.
  • Sie können das System anweisen, die URL automatisch nach einmaliger Verwendung zu widerrufen.

    Wenn Sie sicher sind, dass die URL gelesen wird (indem damit das src-Attribut eines Medienelements festgelegt wird), können Sie den zweiten Parameter der URL.createObjectURL-Methode (oneTimeOnly) auf true (eine Eigenschaftensammlung) festlegen, wenn das System die URL nach abgeschlossenem Lesen des Objekts automatisch widerrufen soll. Beispiel:

    
    var url = URL.createObjectURL(blob, {oneTimeOnly: true});
    
    
    Hinweis  Stellen Sie bei Verwendung einer nicht wiederverwendbaren URL sicher, dass Sie mit der URL das src-Attribut eines audio-, video- oder img-Elements festlegen. Andernfalls wird der interne Verweis vom System nicht freigegeben. Wenn Ihnen nicht bekannt ist, wie oder wann die URL verwendet wird, erstellen Sie die URL bei Bedarf, oder widerrufen Sie die URL stattdessen explizit mit URL.revokeObjectURL.
     
    Hinweis  Blob-Inhalte können nur dann originalgetreu gedruckt werden, wenn Sie eine wiederverwendbare URL verwenden. Wenn Sie also den Inhalt eines Blob drucken möchten, legen Sie die oneTimeOnly-Eigenschaft nicht auf true fest, wenn Sie URL.createObjectURL aufrufen.
     

Erstellen von Medienelementen bei Bedarf und Verwenden eines Posterbilds

Erstellen Sie Medienelemente (beispielsweise das video-Element) erst dann, wenn diese tatsächlich verwendet werden. Beim Erstellen von Medienelementen wird eine beträchtliche CPU- und Arbeitsspeicherkapazität belegt. Erstellen Sie diese also bei Bedarf und nicht im Rahmen eines Massenvorgangs.

Wenn Sie ein video-Element erstellen, das nicht automatisch wiedergegeben wird, legen Sie das poster-Attribut des video-Elements fest. Wenn Sie das poster-Attribut nicht festlegen, muss das Medienmodul mit dem Decodieren des Videos zum Rendern des ersten Bilds beginnen, um ein Posterbild zu erhalten.

Im folgenden Beispiel wird veranschaulicht, wie das poster-Attribut festgelegt wird.


<video src = "video.h264" poster = "poster.png"></video>

Verwenden des ms-appdata://-Schemas zum Laden von Medien

Es gibt zwei gängige Methoden zum Laden von Medien, die am Datenspeicherort Ihrer App gespeichert sind: mit den Speicherungs-APIs und mit dem ms-appdata://-Schema. Die Speicherungs-APIs durchlaufen einen Brokerprozess, um auf die Medien am Datenspeicherort der App zuzugreifen, sodass ihre Ausführung länger dauert. Verwenden Sie anstelle der Speicherungs-APIs das ms-appdata://-Schema, das die Medien im gleichen Prozess lädt und daher viel schneller ist.

 

 

Anzeigen:
© 2016 Microsoft