2017-03-17 3 views
0

Ich versuche eine Anwendung zu erstellen, die unter anderem mehrere Google Charts Timelines zeichnet. Die zum Füllen der Zeitleisten verwendeten Daten werden aus JSON-Dateien abgerufen, von denen einige ziemlich groß sind. Die größte meiner Testdaten ist etwa 30 MB.Google Charts zeichnen() Leistung

Die Google Charts-Dokumentation besagt, dass chart.draw(table, options) asynchron ist. Dies scheint jedoch nicht der Fall zu sein. Wenn ich meine Daten einlade und mit dem Zeichnen der Diagramme beginne, stürzt meine App ab, bis der letzte Diagrammprozess abgeschlossen ist.

// several times, call: 
google.charts.load('current', { 
    packages: ['timeline'], 
    callback: this.layoutTimelineFor_(
    container, 
    this.data[group], 
    group), 
    }); 

// ... 

layoutTimelineFor_: function(container, timeline, group) { 
    return() => { 
    const chart = new google.visualization.Timeline(container); 
    const table = this.mapTimelineToDataTable_(timeline, group); 

    // ... 

    const options = { 
     backgroundColor: 'transparent', 
     height: document.documentDelement.clientHeight/2 - 50, 
     width: (container.parentElement || container) 
     .getBoundingClientRect().width, 
     forceIFrame: true, 
     timeline: { 
     singleColor: '#d5ddf6', 
     }, 
     tooltip: { 
     trigger: 'none', 
     }, 
     hAxis: { 
     minValue: 0, 
     }, 
    }; 

    if (this.duration > 0) { 
     options.hAxis.format = this.pickTimeFormat_(this.duration); 
     options.hAxis.maxValue = this.duration; 
     const p1 = performance.now(); 
     chart.draw(table, options); 
     const p2 = performance.now(); 
     console.log(`${group} chart.draw(table, options) took ${p2-p1}ms`); 
    } else { 
     this.chartQueue_.push({chart, table, options, group}); 
    } 
    } 
} 

// ... 

durationChanged: function() { 
    while (this.chartQueue_.length) { 
    const data = this.chartQueue_.shift(); 
    data.options.hAxis.format = this.pickTimeFormat_(this.duration); 
    data.options.hAxis.maxValue = this.duration; 
    const p1 = performance.now(); 
    data.chart.draw(data.table, data.options); 
    const p2 = performance.now(); 
    console.log(`${data.group} chart.draw(table, options) took ${p2-p1}ms`); 
    } 
} 

Der Ausgang meiner zwei Timern ist etwas in diese Richtung:

label chart.draw(table, options) took 154.26999999999998ms 
shot chart.draw(table, options) took 141.98500000000013ms 
face chart.draw(table, options) took 1601.9849999999997ms 
person chart.draw(table, options) took 13932.140000000001ms 

Diese Zahlen sind in etwa proportional zu der Größe des JSON als Daten für jedes Zeitdiagramm verwendet wird. (Anmerkung: die obigen Zahlen kommen von ~ 20MB der Testdaten, nicht meiner größten.)

Meine Anwendung für 296ms zu sperren wäre unglücklich, aber annehmbar. Verdammt, die meisten Benutzer werden wahrscheinlich auch keine 1,9s Verzögerung bemerken. 15.8s ist inakzeptabel. Und doch Google's guide sagt:

Die draw() Methode ist asynchron, das heißt, es kehrt sofort zurück, aber die Instanz, dass es möglicherweise nicht sofort verfügbar zurück.

Gibt es einen Weg, ich kann draw asynchron ausführen, wie die Dokumentation behauptet, es sollte sein?

+1

Frage nur, ~ 20MB' von Daten, wäre das nicht ein bisschen zu präzise für ein einfaches statistisches Diagramm? Vielleicht solltest du das Zeitfenster eingrenzen oder die Genauigkeit von 1 Sekunde auf 2 Sekunden reduzieren, es wäre 50% kleiner, wodurch es 50% schneller rendern würde. In beiden Fällen sind Async-Aufrufe immer noch stark auf die Browser-Implementation angewiesen. Chrome vs Firefox würde beide andere Ergebnisse anzeigen. – Xorifelse

+0

@WhiteHat, danke. Ich denke, ich habe es nur einmal in einer früheren Version des Codes aufgerufen. Das Zurückschalten auf einen einzelnen load() -Aufruf löst das Problem jedoch nicht. –

+0

@ Xorifelse, die Daten entsprechen einem Video, das an anderer Stelle auf der Seite angezeigt wird. Die größten JSON-Dateien wurden basierend auf dem Video mit 10 Bildern pro Sekunde erstellt. Die obige Nummer 13932.14ms stammt aus einer Datei mit der allgemeinen Struktur '{" id ":" 4574491 "," Anmerkungen ": {" person ": [... 26661 Objekte]}}' –

Antwort

0

Nach weiterer Forschung scheint es, dass nur die tatsächliche Zeichnung des Diagramms asynchron ist. Bevor die Zeichnung beginnt, durchlaufen die Daten einen (synchronen) Verarbeitungsschritt, der die Ursache meines Problems ist. Es gibt keine Lösung für das Timeline-Diagramm mit einem Datensatz, der so groß ist wie meiner.

Core Charts (Bereich, Balken, Bubble, Candlestick, Spalte, Combo, Histogramm, Linie, Pie, Scatter und Stepped Area) haben eine allowAsync Option as of version 41, die diesen Verarbeitungsschritt in Stücke aufteilt, so dass der gesamte Prozess kann unterbrochen werden (obwohl jeder Brocken nicht kann). Timeline ist leider kein Kerndiagramm und hat diese Option nicht.