LCOV - code coverage report
Current view: top level - dashql-app/src/session/scripts - script_statistics_bar.tsx Coverage Total Hit
Test: DashQL 915828b Lines: 100.0 % 99 99
Test Date: 2026-11-06 19:30:32

            Line data    Source code
       1              : import * as dashql from '@ankoh/dashql-core';
       2              : 
       3              : import * as React from 'react';
       4              : import * as Immutable from 'immutable';
       5              : 
       6              : import { formatBytes, formatNanoseconds } from '../../utils/format.js';
       7              : import { classNames } from '../../utils/classnames.js';
       8              : 
       9              : import * as styles from './script_statistics_bar.module.css';
      10              : 
      11              : interface HistoryProps {
      12              :     data: Float64Array;
      13              :     maximum: number;
      14              : }
      15              : 
      16            1 : const History: React.FC<HistoryProps> = (props: HistoryProps) => {
      17            1 :     const out = [];
      18            1 :     const scaledMax = props.maximum * 1.2;
      19            1 :     for (let i = 0; i < props.data.length; ++i) {
      20            1 :         const percent = (props.data[i] * 100) / scaledMax;
      21            1 :         out.push(
      22            1 :             <div
      23            1 :                 key={i}
      24            1 :                 style={{
      25            1 :                     height: `${percent}%`,
      26            1 :                     backgroundColor: 'var(--color_border)',
      27            1 :                 }}
      28            1 :             />,
      29            1 :         );
      30            1 :     }
      31            1 :     return <div className={styles.metric_history}>{out}</div>;
      32            1 : };
      33              : 
      34              : interface Props {
      35              :     className?: string;
      36              :     stats: Immutable.List<dashql.buffers.editor.EditorProcessingStatisticsT> | null;
      37              : }
      38              : 
      39            1 : export const ScriptStatisticsBar: React.FC<Props> = (props: Props) => {
      40            1 :     const stats = props.stats ?? Immutable.List();
      41            1 :     if (stats.isEmpty()) {
      42            1 :         return (
      43            1 :             <div className={classNames(props.className, styles.container)}>
      44            1 :                 <div className={styles.metric_container}>
      45            1 :                     <div className={styles.metric_last_reading}>- us</div>
      46            1 :                 </div>
      47            1 :                 <div className={styles.metric_container}>
      48            1 :                     <div className={styles.metric_last_reading}>- bytes</div>
      49            1 :                 </div>
      50            1 :             </div>
      51              :         );
      52              :     }
      53              : 
      54            1 :     const computeTotalMemory = (reading: dashql.buffers.editor.EditorProcessingStatisticsT) =>
      55            1 :         Number(reading.ropeBytes
      56            1 :             + reading.scannerInputBytes
      57            1 :             + reading.scannerNameDictionaryBytes
      58            1 :             + reading.parserAstBytes
      59            1 :             + reading.analyzerDescriptionBytes
      60            1 :             + reading.analyzerNameIndexBytes);
      61              : 
      62            1 :     const last = stats.last()!;
      63            1 :     const lastElapsedScanner = last.scannerLastElapsedNs;
      64            1 :     const lastElapsedParser = last.parserLastElapsedNs;
      65            1 :     const lastElapsedAnalyzer = last.analyzerLastElapsedNs;
      66            1 :     const lastTotalMemory = computeTotalMemory(last);
      67              : 
      68            1 :     const n = Math.min(stats.size, 20);
      69            1 :     const bufferSize = Math.max(n, 20);
      70            1 :     const elapsedScannerHistory = new Float64Array(bufferSize);
      71            1 :     const elapsedParserHistory = new Float64Array(bufferSize);
      72            1 :     const elapsedAnalyzerHistory = new Float64Array(bufferSize);
      73            1 :     const memoryHistory = new Float64Array(bufferSize);
      74            1 :     let maxElapsedScanner = 0;
      75            1 :     let maxElapsedParser = 0;
      76            1 :     let maxElapsedAnalyzer = 0;
      77            1 :     let maxTotalMemory = 0;
      78            1 :     let writer = 0;
      79            1 :     for (const reading of stats.toSeq().take(n)) {
      80            1 :         const totalMemory = computeTotalMemory(reading);
      81            1 :         const elapsedScanner = reading.scannerLastElapsedNs;
      82            1 :         const elapsedParser = reading.parserLastElapsedNs;
      83            1 :         const elapsedAnalyzer = reading.analyzerLastElapsedNs;
      84            1 :         elapsedScannerHistory[writer] = elapsedScanner;
      85            1 :         elapsedParserHistory[writer] = elapsedParser;
      86            1 :         elapsedAnalyzerHistory[writer] = elapsedAnalyzer;
      87            1 :         memoryHistory[writer] = totalMemory;
      88            1 :         maxElapsedScanner = Math.max(maxElapsedScanner, elapsedScanner);
      89            1 :         maxElapsedParser = Math.max(maxElapsedParser, elapsedParser);
      90            1 :         maxElapsedAnalyzer = Math.max(maxElapsedAnalyzer, elapsedAnalyzer);
      91            1 :         maxTotalMemory = Math.max(maxTotalMemory, totalMemory);
      92            1 :         ++writer;
      93            1 :     }
      94              : 
      95            1 :     return (
      96            1 :         <div className={classNames(props.className, styles.container)}>
      97            1 :             <div className={styles.metric_container}>
      98            1 :                 <History data={memoryHistory} maximum={maxTotalMemory} />
      99            1 :                 <div className={styles.metric_text_overlay}>
     100            1 :                     <div className={styles.metric_name}>M</div>
     101            1 :                     <div className={styles.metric_last_reading}>{formatBytes(lastTotalMemory)}</div>
     102            1 :                 </div>
     103            1 :             </div>
     104            1 :             <div className={styles.metric_container}>
     105            1 :                 <History data={elapsedScannerHistory} maximum={maxElapsedScanner} />
     106            1 :                 <div className={styles.metric_text_overlay}>
     107            1 :                     <div className={styles.metric_name}>S</div>
     108            1 :                     <div className={styles.metric_last_reading}>{formatNanoseconds(lastElapsedScanner)}</div>
     109            1 :                 </div>
     110            1 :             </div>
     111            1 :             <div className={styles.metric_container}>
     112            1 :                 <History data={elapsedParserHistory} maximum={maxElapsedParser} />
     113            1 :                 <div className={styles.metric_text_overlay}>
     114            1 :                     <div className={styles.metric_name}>P</div>
     115            1 :                     <div className={styles.metric_last_reading}>{formatNanoseconds(lastElapsedParser)}</div>
     116            1 :                 </div>
     117            1 :             </div>
     118            1 :             <div className={styles.metric_container}>
     119            1 :                 <History data={elapsedAnalyzerHistory} maximum={maxElapsedAnalyzer} />
     120            1 :                 <div className={styles.metric_text_overlay}>
     121            1 :                     <div className={styles.metric_name}>A</div>
     122            1 :                     <div className={styles.metric_last_reading}>{formatNanoseconds(lastElapsedAnalyzer)}</div>
     123            1 :                 </div>
     124            1 :             </div>
     125            1 :         </div>
     126              :     );
     127            1 : };
        

Generated by: LCOV version 2.0-1