Skip to content

Commit

Permalink
Merge branch 'develop' into feature/issue-1358
Browse files Browse the repository at this point in the history
  • Loading branch information
sequba committed Jan 30, 2024
2 parents 84351e2 + 3a7aafb commit 8f108d5
Show file tree
Hide file tree
Showing 11 changed files with 82 additions and 99 deletions.
4 changes: 4 additions & 0 deletions docs/guide/integration-with-vue.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,10 @@ For more details, see the [client-side installation](client-side-installation.md

## Demo

::: tip
This demo uses the [Vue 3](https://v3.vuejs.org/) framework. If you are looking for an example using Vue 2, check out the [code on GitHub](https://github.com/handsontable/hyperformula-demos/tree/2.5.x/vue-demo).
:::

<iframe
src="https://codesandbox.io/p/devbox/github/handsontable/hyperformula-demos/tree/2.6.x/vue-3-demo"
style="width:100%; height:1070px; border:0; border-radius: 4px; overflow:hidden;"
Expand Down
10 changes: 5 additions & 5 deletions test/performance/basic-benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import {expectedValues as expectedValuesB, sheet as sheetBGenerator} from './she
import {sheet as columnRangesGenerator} from './sheets/column-ranges'

export function runBasicBenchmark(): BenchmarkResult[] {
const result: BenchmarkResult[] = []
const sheetA = sheetAGenerator()
const sheetB = sheetBGenerator()
const sheetT = sheetTGenerator()
const infiniteRanges = columnRangesGenerator()

const result: BenchmarkResult[] = []
batch(result,
() => benchmark('Sheet A', sheetA, expectedValuesA(sheetA), {numberOfRuns: 100}),
() => benchmark('Sheet B', sheetB, expectedValuesB(sheetB), {numberOfRuns: 100}),
() => benchmark('Sheet T', sheetT, expectedValuesT(sheetT), {numberOfRuns: 100}),
() => benchmark('Sheet A', sheetA, expectedValuesA(sheetA), { numberOfRuns: 100 }),
() => benchmark('Sheet B', sheetB, expectedValuesB(sheetB), { numberOfRuns: 100 }),
() => benchmark('Sheet T', sheetT, expectedValuesT(sheetT), { numberOfRuns: 100 }),
() => benchmark('Column ranges', infiniteRanges, [{
address: 'AX50',
value: 1.04519967355127e+63
}], {expectedTime: 1000, numberOfRuns: 100})
}], { expectedTime: 1000, numberOfRuns: 100 })
)

return result
Expand Down
60 changes: 41 additions & 19 deletions test/performance/benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import {
average,
EnrichedStatType,
enrichStatistics,
ExtStatType,
measureCruds,
reduceStats,
Stats,
Expand Down Expand Up @@ -39,38 +38,57 @@ export interface BenchmarkResult {
statistics: Stats,
}

export function benchmark(name: string, sheet: Sheet, expectedValues: ExpectedValue[], config: Partial<Config> = defaultConfig): Maybe<BenchmarkResult> {
export function benchmark(
name: string,
sheet: Sheet,
expectedValues: ExpectedValue[],
config: Partial<Config> = defaultConfig
): Maybe<BenchmarkResult> {
const runEngine = (engineConfig?: Partial<ConfigParams>) => HyperFormula.buildFromArray(sheet, engineConfig)
return benchmarkBuild(name, runEngine, expectedValues, config)
}

export function benchmarkCruds(name: string, sheet: Sheet, cruds: (engine: HyperFormula) => void,
expectedValues: ExpectedValue[], userConfig: Partial<Config> = defaultConfig): Maybe<BenchmarkResult> {
export function benchmarkCruds(
name: string,
sheet: Sheet,
cruds: (engine: HyperFormula) => void,
expectedValues: ExpectedValue[],
userConfig: Partial<Config> = defaultConfig,
): Maybe<BenchmarkResult> {
console.info(`=== Benchmark - ${name} === `)

const config = Object.assign({}, defaultConfig, userConfig)
const engineConfig = Object.assign({}, config.engineConfig, defaultEngineConfig)

const engine = HyperFormula.buildFromArray(sheet, engineConfig)
const statistics: Stats[] = []

let currentRun = 0
let engine: HyperFormula | undefined

do {
engine = HyperFormula.buildFromArray(sheet, engineConfig)
statistics.push(enrichStatistics(measureCruds(engine, name, cruds)))

const statistics = measureCruds(engine, name, cruds)
currentRun++

if (!validate(engine, expectedValues)) {
console.error('Sheet validation error')
if (process.exit) {
process.exit(1)
if (!validate(engine, expectedValues)) {
console.error('Sheet validation error')
if (process.exit) {
process.exit(1)
}
return
}
return
}
} while (currentRun < config.numberOfRuns)

const totalTime = statistics.get(ExtStatType.CRUDS_TOTAL) || 0
statsTreePrintCruds(statistics)
const averages = reduceStats(statistics, average)
const totalTime = averages.get(EnrichedStatType.CRUDS_TOTAL) || 0
statsTreePrintCruds(averages)

return {
name: name,
engine: engine,
totalTime: totalTime,
statistics: statistics,
statistics: averages,
}
}

Expand All @@ -83,14 +101,18 @@ export function batch(stats: BenchmarkResult[], ...benchmarks: (() => Maybe<Benc
}
}

function benchmarkBuild(name: string, runEngine: (engineConfig?: Partial<ConfigParams>) => HyperFormula,
expectedValues: ExpectedValue[], userConfig: Partial<Config> = defaultConfig): Maybe<BenchmarkResult> {
function benchmarkBuild(
name: string,
runEngine: (engineConfig?: Partial<ConfigParams>) => HyperFormula,
expectedValues: ExpectedValue[],
userConfig: Partial<Config> = defaultConfig,
): Maybe<BenchmarkResult> {
console.info(`=== Benchmark - ${name} === `)

const config = Object.assign({}, defaultConfig, userConfig)
const engineConfig = Object.assign({}, config.engineConfig, defaultEngineConfig)

const statistics: Map<EnrichedStatType, number>[] = []
const statistics: Stats[] = []

let currentRun = 0
let engine: HyperFormula
Expand All @@ -111,8 +133,8 @@ function benchmarkBuild(name: string, runEngine: (engineConfig?: Partial<ConfigP
} while (currentRun < config.numberOfRuns)

const averages = reduceStats(statistics, average)
statsTreePrint(averages)
const totalTime = averages.get(EnrichedStatType.BUILD_ENGINE_TOTAL) || 0
statsTreePrint(averages)

return {
name: name,
Expand Down
23 changes: 13 additions & 10 deletions test/performance/cruds-benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,22 @@ import {adr} from './utils/utils'

export function runCrudsBenchmark(): BenchmarkResult[] {
const result: BenchmarkResult[] = []
const sheetA = sheetAGenerator(10000)
const sheetB = sheetBGenerator(5000)
const columnRanges = columnRangesGenerator()

batch(result,
() => benchmarkCruds('Sheet A: change value, add/remove row/column', sheetAGenerator(10000), (engine: HyperFormula) => {
() => benchmarkCruds('Sheet A: change value, add/remove row/column', sheetA, (engine: HyperFormula) => {
engine.setCellContents(adr('A1'), '123')
engine.addRows(0, [5000, 1])
engine.removeRows(0, [8000, 1])
engine.addColumns(0, [0, 1])
engine.removeColumns(0, [0, 1])
}, [
{address: 'E7000', value: -1.17344394901827e+23},
]),
], { numberOfRuns: 100 }),

() => benchmarkCruds('Sheet B: change value, add/remove row/column', sheetBGenerator(5000), (engine: HyperFormula) => {
() => benchmarkCruds('Sheet B: change value, add/remove row/column', sheetB, (engine: HyperFormula) => {
engine.setCellContents(adr('A1'), '123')
engine.addRows(0, [2000, 1])
engine.removeRows(0, [3000, 1])
Expand All @@ -28,26 +31,26 @@ export function runCrudsBenchmark(): BenchmarkResult[] {
}, [
{address: 'E50', value: 1347},
{address: 'E2002', value: 2001122},
]),
], { numberOfRuns: 100 }),

() => benchmarkCruds('Column ranges - add column', columnRangesGenerator(), (engine: HyperFormula) => {
() => benchmarkCruds('Column ranges - add column', columnRanges, (engine: HyperFormula) => {
engine.addColumns(0, [1, 1])
engine.setCellContents(adr('A1'), 5)
}, [
{address: 'AY50', value: 3.47832712968835e+63},
]),
], { numberOfRuns: 100 }),

() => benchmarkCruds('Column ranges - without batch', columnRangesGenerator(), (engine: HyperFormula) => {
() => benchmarkCruds('Column ranges - without batch', columnRanges, (engine: HyperFormula) => {
engine.setCellContents(adr('A1'), 1)
engine.setCellContents(adr('A1'), 2)
engine.setCellContents(adr('A1'), 3)
engine.setCellContents(adr('A1'), 4)
engine.setCellContents(adr('A1'), 5)
}, [
{address: 'AX50', value: 3.47832712968835e+63},
]),
], { numberOfRuns: 100 }),

() => benchmarkCruds('Column ranges - batch', columnRangesGenerator(), (engine: HyperFormula) => {
() => benchmarkCruds('Column ranges - batch', columnRanges, (engine: HyperFormula) => {
engine.batch(() => {
engine.setCellContents(adr('A1'), 1)
engine.setCellContents(adr('A1'), 2)
Expand All @@ -57,7 +60,7 @@ export function runCrudsBenchmark(): BenchmarkResult[] {
})
}, [
{address: 'AX50', value: 3.47832712968835e+63},
])
], { numberOfRuns: 100 })
)

return result
Expand Down
9 changes: 5 additions & 4 deletions test/performance/sheets/05-sheet-t.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
import {ExpectedValue} from '../benchmark'
import {RawCellContent, Sheet} from '../../../src'

export function sheet(rows: number = 10000) {
const sheet = []
export function sheet(rows: number = 10000): Sheet {
const sheet: Sheet = []

let prev = 1

const prettyRandomString = (chars: number) => [...Array(chars)].map(() => (~~(Math.random() * 36)).toString(36)).join('')

while (prev <= rows) {
const rowToPush = [
const rowToPush: RawCellContent[] = [
prettyRandomString(30),
prettyRandomString(30),
`=CONCATENATE(A${prev}, B${prev})`,
Expand All @@ -20,7 +21,7 @@ export function sheet(rows: number = 10000) {
return sheet
}

export function expectedValues(sheet: string[][]): ExpectedValue[] {
export function expectedValues(sheet: Sheet): ExpectedValue[] {
return [
{address: 'C1', value: `${sheet[0][0]}${sheet[0][1]}`},
{address: 'C1000', value: `${sheet[999][0]}${sheet[999][1]}`},
Expand Down
9 changes: 5 additions & 4 deletions test/performance/sheets/09-sheet-a.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {RawCellContent, Sheet} from '../../../src'
import {ExpectedValue} from '../benchmark'

export function sheet(rows: number = 10000) {
const sheet = []
export function sheet(rows: number = 10000): Sheet {
const sheet: Sheet = []
sheet.push(['1', '2', '3', '4', '5'])

let prev = 1

while (prev < rows) {
const rowToPush = [
const rowToPush: RawCellContent[] = [
`${prev + 1}`,
'3',
`=A${prev}*A${prev}`,
Expand All @@ -21,7 +22,7 @@ export function sheet(rows: number = 10000) {
return sheet
}

export function expectedValues(_sheet: string[][]): ExpectedValue[] {
export function expectedValues(_sheet: Sheet): ExpectedValue[] {
return [
{address: 'A10000', value: 10000},
{address: 'B10000', value: 3},
Expand Down
9 changes: 5 additions & 4 deletions test/performance/sheets/10-sheet-b.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import {ExpectedValue} from '../benchmark'
import {RawCellContent, Sheet} from '../../../src'

export function sheet(rows: number = 5000) {
const sheet = []
export function sheet(rows: number = 5000): Sheet {
const sheet: Sheet = []
sheet.push(['1', '2', '3', '0', '0'])

let prev = 1

while (prev < rows) {
const rowToPush = [
const rowToPush: RawCellContent[] = [
`${prev + 1}`,
'2',
'=3*5',
Expand All @@ -21,7 +22,7 @@ export function sheet(rows: number = 5000) {
return sheet
}

export function expectedValues(_sheet: string[][]): ExpectedValue[] {
export function expectedValues(_sheet: Sheet): ExpectedValue[] {
return [
{address: 'A5000', value: 5000},
{address: 'B5000', value: 2},
Expand Down
2 changes: 1 addition & 1 deletion test/performance/sheets/column-ranges.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import {RawCellContent, Sheet} from '../../../src'
import {columnIndexToLabel, simpleCellAddressToString} from '../../../src/parser/addressRepresentationConverters'

export function sheet(cols: number = 50) {
export function sheet(cols: number = 50): Sheet {
const sheet: Sheet = []

const firstRow: RawCellContent[] = [1]
Expand Down
20 changes: 0 additions & 20 deletions test/performance/sheets/median-evaluation.ts

This file was deleted.

23 changes: 2 additions & 21 deletions test/performance/utils/stats.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ export type Stats = Map<EnrichedStatType, number>

export enum ExtStatType {
INIT_DATASTRUCTURES = 'INIT_DATASTRUCTURES',
PREPROCESSING = 'PREPROCESING',
PREPROCESSING = 'PREPROCESSING',
CRUDS_TOTAL = 'CRUDS_TOTAL',
}

Expand Down Expand Up @@ -84,23 +84,4 @@ export function average(values: number[]): number {
return sum + value
}, 0)
return sum / values.length
}

export function median(values: number[]): number {
return values.sort((a, b) => a - b)[Math.trunc(values.length / 2)]
}

export function stdDev(values: number[]): number {
const avg = average(values)
const sqrDiffs = squareDiffs(values, avg)
const avgSquareDiffs = average(sqrDiffs)

return Math.sqrt(avgSquareDiffs)
}

function squareDiffs(values: number[], avg: number): number[] {
return values.map((value) => {
const diff = value - avg
return diff * diff
})
}
}
12 changes: 1 addition & 11 deletions test/performance/utils/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {HyperFormula, SimpleCellAddress} from '../../../src'
import {SimpleCellAddress} from '../../../src'

export const adr = (stringAddress: string, sheet: number = 0): SimpleCellAddress => {
const result = /^(\$([A-Za-z0-9_]+)\.)?(\$?)([A-Za-z]+)(\$?)([0-9]+)$/.exec(stringAddress)!
Expand All @@ -15,13 +15,3 @@ const colNumber = (input: string): number => {
}, 0) - 1
}
}

export function numberOfRows(engine: HyperFormula) {
const dimensions = engine.getAllSheetsDimensions()
let sum = 0
const sheetNames = Object.getOwnPropertyNames(dimensions)
for (const sheet of sheetNames) {
sum += dimensions[sheet].height
}
return sum
}

0 comments on commit 8f108d5

Please sign in to comment.