From e83dbecd96616f45d87799e7c59141a5388a6e05 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 16 Jun 2025 16:20:57 -0400 Subject: [PATCH 01/45] add performance tests --- .circleci/config.yml | 25 ++++++ .circleci/test.sh | 5 ++ package.json | 1 + tasks/test_performance.js | 46 ++++++++++ tasks/util/constants.js | 1 + test/jasmine/karma.conf.js | 19 +++- test/jasmine/performance_tests/bar_test.js | 89 +++++++++++++++++++ .../jasmine/performance_tests/scatter_test.js | 87 ++++++++++++++++++ 8 files changed, 269 insertions(+), 4 deletions(-) create mode 100644 tasks/test_performance.js create mode 100644 test/jasmine/performance_tests/bar_test.js create mode 100644 test/jasmine/performance_tests/scatter_test.js diff --git a/.circleci/config.yml b/.circleci/config.yml index b5d94298735..6701dd7e259 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -33,6 +33,28 @@ jobs: paths: - plotly.js + performance-jasmine: + docker: + # need '-browsers' version to test in real (xvfb-wrapped) browsers + - image: cimg/node:18.20.4-browsers + environment: + # Alaska time (arbitrary timezone to test date logic) + TZ: "America/Anchorage" + working_directory: ~/plotly.js + steps: + - run: sudo apt-get update + - browser-tools/install-browser-tools: + install-firefox: false + install-geckodriver: false + install-chrome: true + chrome-version: "132.0.6834.110" + - attach_workspace: + at: ~/ + - run: + name: Run performance tests + command: .circleci/test.sh performance-jasmine + + timezone-jasmine: docker: # need '-browsers' version to test in real (xvfb-wrapped) browsers @@ -500,6 +522,9 @@ workflows: - bundle-jasmine: requires: - install-and-cibuild + - performance-jasmine: + requires: + - install-and-cibuild - mathjax-firefoxLatest: requires: - install-and-cibuild diff --git a/.circleci/test.sh b/.circleci/test.sh index b814c1dd3e8..4df91e8af8c 100755 --- a/.circleci/test.sh +++ b/.circleci/test.sh @@ -79,6 +79,11 @@ case $1 in exit $EXIT_STATE ;; + performance-jasmine) + npm run test-performance || EXIT_STATE=$? + exit $EXIT_STATE + ;; + mathjax-firefox) ./node_modules/karma/bin/karma start test/jasmine/karma.conf.js --FF --bundleTest=mathjax --nowatch || EXIT_STATE=$? exit $EXIT_STATE diff --git a/package.json b/package.json index 39f76f1a5dd..94dd2045e0d 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,7 @@ "test-export": "node test/image/export_test.js", "test-syntax": "node tasks/test_syntax.js && npm run find-strings -- --no-output", "test-bundle": "node tasks/test_bundle.js", + "test-performance": "node tasks/test_performance.js", "test-plain-obj": "node tasks/test_plain_obj.mjs", "test": "npm run test-jasmine -- --nowatch && npm run test-bundle && npm run test-image && npm run test-export && npm run test-syntax && npm run lint", "b64": "python3 test/image/generate_b64_mocks.py && node devtools/test_dashboard/server.mjs", diff --git a/tasks/test_performance.js b/tasks/test_performance.js new file mode 100644 index 00000000000..1d1c9487536 --- /dev/null +++ b/tasks/test_performance.js @@ -0,0 +1,46 @@ +var path = require('path'); +var exec = require('child_process').exec; +var { glob } = require('glob'); +var runSeries = require('run-series'); + +var constants = require('./util/constants'); +var pathToJasminePerformanceTests = constants.pathToJasminePerformanceTests; + +/** + * Run all jasmine 'performance' test in series + * + * To run specific performance tests, use + * + * $ npm run test-jasmine -- --performanceTest= + */ +glob(pathToJasminePerformanceTests + '/*.js').then(function(files) { + var tasks = files.map(function(file) { + return function(cb) { + var cmd = [ + 'karma', 'start', + path.join(constants.pathToRoot, 'test', 'jasmine', 'karma.conf.js'), + '--performanceTest=' + path.basename(file), + '--nowatch' + ].join(' '); + + console.log('Running: ' + cmd); + + exec(cmd, function(err) { + cb(null, err); + }).stdout.pipe(process.stdout); + }; + }); + + runSeries(tasks, function(err, results) { + if(err) throw err; + + var failed = results.filter(function(r) { return r; }); + + if(failed.length) { + console.log('\ntest-performance summary:'); + failed.forEach(function(r) { console.warn('- ' + r.cmd + ' failed'); }); + console.log(''); + process.exit(1); + } + }); +}); diff --git a/tasks/util/constants.js b/tasks/util/constants.js index 6442501d9aa..69c1e88d64d 100644 --- a/tasks/util/constants.js +++ b/tasks/util/constants.js @@ -225,6 +225,7 @@ module.exports = { pathToJasmineTests: path.join(pathToRoot, 'test/jasmine/tests'), pathToJasmineBundleTests: path.join(pathToRoot, 'test/jasmine/bundle_tests'), + pathToJasminePerformanceTests: path.join(pathToRoot, 'test/jasmine/performance_tests'), // this mapbox access token is 'public', no need to hide it // more info: https://www.mapbox.com/help/define-access-token/ diff --git a/test/jasmine/karma.conf.js b/test/jasmine/karma.conf.js index f66235d7593..4653e346f44 100644 --- a/test/jasmine/karma.conf.js +++ b/test/jasmine/karma.conf.js @@ -8,7 +8,7 @@ var esbuildConfig = require('../../esbuild-config.js'); var isCI = Boolean(process.env.CI); var argv = minimist(process.argv.slice(4), { - string: ['bundleTest', 'width', 'height'], + string: ['bundleTest', 'performanceTest', 'width', 'height'], boolean: [ 'mathjax3', 'info', @@ -21,6 +21,7 @@ var argv = minimist(process.argv.slice(4), { Chrome: 'chrome', Firefox: ['firefox', 'FF'], bundleTest: ['bundletest', 'bundle_test'], + performanceTest: ['performancetest', 'performance_test'], nowatch: 'no-watch', failFast: 'fail-fast', }, @@ -53,7 +54,8 @@ if(argv.info) { ' - All non-flagged arguments corresponds to the test suites in `test/jasmine/tests/` to be run.', ' No need to add the `_test.js` suffix, we expand them correctly here.', ' - `--bundleTest` set the bundle test suite `test/jasmine/bundle_tests/ to be run.', - ' Note that only one bundle test can be run at a time.', + ' - `--performanceTest` set the bundle test suite `test/jasmine/performance_tests/ to be run.', + ' Note that only one bundle/performance test can be run at a time.', ' - Use `--tags` to specify which `@` tags to test (if any) e.g `npm run test-jasmine -- --tags=gl`', ' will run only gl tests.', ' - Use `--skip-tags` to specify which `@` tags to skip (if any) e.g `npm run test-jasmine -- --skip-tags=gl`', @@ -100,7 +102,8 @@ var glob = function(_) { }; var isBundleTest = !!argv.bundleTest; -var isFullSuite = !isBundleTest && argv._.length === 0; +var isPerformanceTest = !!argv.performanceTest; +var isFullSuite = !(isBundleTest || isPerformanceTest) && argv._.length === 0; var testFileGlob; if(isFullSuite) { @@ -113,6 +116,14 @@ if(isFullSuite) { } testFileGlob = path.join(__dirname, 'bundle_tests', glob([basename(_[0])])); +} else if(isPerformanceTest) { + var _ = merge(argv.performanceTest); + + if(_.length > 1) { + console.warn('Can only run one performance test suite at a time, ignoring ', _.slice(1)); + } + + testFileGlob = path.join(__dirname, 'performance_tests', glob([basename(_[0])])); } else { testFileGlob = path.join(__dirname, 'tests', glob(merge(argv._).map(basename))); } @@ -250,7 +261,7 @@ func.defaultConfig = { '--touch-events', '--window-size=' + argv.width + ',' + argv.height, isCI ? '--ignore-gpu-blacklist' : '', - (isBundleTest && basename(testFileGlob) === 'no_webgl') ? '--disable-webgl' : '' + ((isBundleTest || isPerformanceTest) && basename(testFileGlob) === 'no_webgl') ? '--disable-webgl' : '' ] }, _Firefox: { diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js new file mode 100644 index 00000000000..8392bc0941c --- /dev/null +++ b/test/jasmine/performance_tests/bar_test.js @@ -0,0 +1,89 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyBar = require('../../../lib/bar'); + +var gd = createGraphDiv(); + +[{ + n: 1000, averageCap: 75 +}, { + n: 2000, averageCap: 100 +}, { + n: 4000, averageCap: 150 +}, { + n: 8000, averageCap: 300 +}, { + n: 16000, averageCap: 600 +}, { + n: 32000, averageCap: 1200 +}, { + n: 64000, averageCap: 2400 +}].forEach(function(spec) { + describe('Bundle with bar | size:' + spec.n, function() { + 'use strict'; + + Plotly.register(PlotlyBar); + + const samples = Array.from({ length: 5 }, (_, i) => i); + const nTimes = samples.length - 1; + + var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'bar', + y: y + }], + layout: { + width: 1200, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph bar traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + console.log('________________________________'); + console.log('number of points in bar: ' + spec.n); + console.log('expected average (cap): ' + spec.averageCap + ' ms'); + } + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + console.log('max: ' + maxDelta); + console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.trace.bars'); + expect(nodes.size()).toEqual(1); + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js new file mode 100644 index 00000000000..23634877680 --- /dev/null +++ b/test/jasmine/performance_tests/scatter_test.js @@ -0,0 +1,87 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); + +var gd = createGraphDiv(); + +[{ + n: 1000, averageCap: 75 +}, { + n: 2000, averageCap: 100 +}, { + n: 4000, averageCap: 150 +}, { + n: 8000, averageCap: 300 +}, { + n: 16000, averageCap: 600 +}, { + n: 32000, averageCap: 1200 +}, { + n: 64000, averageCap: 2400 +}].forEach(function(spec) { + describe('Bundle with scatter | size:' + spec.n, function() { + 'use strict'; + + const samples = Array.from({ length: 5 }, (_, i) => i); + const nTimes = samples.length - 1; + + var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'scatter', + mode: 'markers', + y: y + }], + layout: { + width: 1200, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph scatter traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + console.log('________________________________'); + console.log('number of points in scatter: ' + spec.n); + console.log('expected average (cap): ' + spec.averageCap + ' ms'); + } + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + console.log('max: ' + maxDelta); + console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.trace.scatter'); + expect(nodes.size()).toEqual(1); + }); + }); + }); +}); From 012abcabeb33155b292975ec9db9894be2d546c4 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 19 Jun 2025 09:39:10 -0400 Subject: [PATCH 02/45] collect performance data and create test report --- test/jasmine/performance_tests/bar_test.js | 34 +++-- test/jasmine/performance_tests/box_test.js | 102 +++++++++++++++ .../jasmine/performance_tests/contour_test.js | 112 +++++++++++++++++ .../jasmine/performance_tests/heatmap_test.js | 112 +++++++++++++++++ .../performance_tests/histogram_test.js | 101 +++++++++++++++ test/jasmine/performance_tests/image_test.js | 119 ++++++++++++++++++ .../jasmine/performance_tests/scatter_test.js | 34 +++-- 7 files changed, 592 insertions(+), 22 deletions(-) create mode 100644 test/jasmine/performance_tests/box_test.js create mode 100644 test/jasmine/performance_tests/contour_test.js create mode 100644 test/jasmine/performance_tests/heatmap_test.js create mode 100644 test/jasmine/performance_tests/histogram_test.js create mode 100644 test/jasmine/performance_tests/image_test.js diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 8392bc0941c..4276c4c3840 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -6,7 +6,7 @@ var PlotlyBar = require('../../../lib/bar'); var gd = createGraphDiv(); -[{ +var tests = [{ n: 1000, averageCap: 75 }, { n: 2000, averageCap: 100 @@ -20,13 +20,15 @@ var gd = createGraphDiv(); n: 32000, averageCap: 1200 }, { n: 64000, averageCap: 2400 -}].forEach(function(spec) { - describe('Bundle with bar | size:' + spec.n, function() { +}]; + +tests.forEach(function(spec, index) { + describe('Performance test bar | size:' + spec.n, function() { 'use strict'; Plotly.register(PlotlyBar); - const samples = Array.from({ length: 5 }, (_, i) => i); + const samples = Array.from({ length: 9 }, (_, i) => i); const nTimes = samples.length - 1; var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); @@ -37,7 +39,7 @@ var gd = createGraphDiv(); y: y }], layout: { - width: 1200, + width: 900, height: 400 } }; @@ -62,27 +64,37 @@ var gd = createGraphDiv(); var delta = Date.now() - startTime; if(t === 0) { - console.log('________________________________'); - console.log('number of points in bar: ' + spec.n); - console.log('expected average (cap): ' + spec.averageCap + ' ms'); + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; } + tests[index].raw[t] = delta; if(t > 0) { // we skip the first run which is slow maxDelta = Math.max(maxDelta, delta); aveDelta += delta / nTimes; } - console.log('turn: ' + t + ' | ' + delta + ' ms'); + // console.log('turn: ' + t + ' | ' + delta + ' ms'); if(t === nTimes) { - console.log('max: ' + maxDelta); - console.log('ave: ' + aveDelta); + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.bars'); expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } }); }); }); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js new file mode 100644 index 00000000000..65e4ff374c0 --- /dev/null +++ b/test/jasmine/performance_tests/box_test.js @@ -0,0 +1,102 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyBox = require('../../../lib/box'); + +var gd = createGraphDiv(); + +var tests = [{ + n: 1000, averageCap: 75 +}, { + n: 2000, averageCap: 100 +}, { + n: 4000, averageCap: 150 +}, { + n: 8000, averageCap: 300 +}, { + n: 16000, averageCap: 600 +}, { + n: 32000, averageCap: 1200 +}, { + n: 64000, averageCap: 2400 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test box | size:' + spec.n, function() { + 'use strict'; + + Plotly.register(PlotlyBox); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'box', + boxpoints: 'all', + y: y + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph box traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + // console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.trace.boxes'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js new file mode 100644 index 00000000000..00b4893fa62 --- /dev/null +++ b/test/jasmine/performance_tests/contour_test.js @@ -0,0 +1,112 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyContour = require('../../../lib/contour'); + +var gd = createGraphDiv(); + +var tests = [{ + nx: 50, ny: 20, averageCap: 100 +}, { + nx: 100, ny: 40, averageCap: 125 +}, { + nx: 200, ny: 80, averageCap: 250 +}, { + nx: 400, ny: 160, averageCap: 500 +}, { + nx: 800, ny: 320, averageCap: 1000 +}, { + nx: 1600, ny: 640, averageCap: 2000 +}, { + nx: 3200, ny: 1280, averageCap: 4000 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test contour | size:' + spec.nx + 'X' + spec.ny, function() { + 'use strict'; + + Plotly.register(PlotlyContour); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var A = spec.nx; + var B = spec.ny; + spec.n = A * B; + + var x = Uint16Array.from({ length: A }, (_, i) => i); + var y = Uint16Array.from({ length: B }, (_, i) => i); + var z = []; + for(var k = 0; k < B ; k++) { + z[k] = Float64Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); + } + + var mock = { + data: [{ + type: 'contour', + x: x, + y: y, + z: z + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph contour traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + // console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.contourlayer'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js new file mode 100644 index 00000000000..454624bb716 --- /dev/null +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -0,0 +1,112 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyHeatmap = require('../../../lib/heatmap'); + +var gd = createGraphDiv(); + +var tests = [{ + nx: 50, ny: 20, averageCap: 75 +}, { + nx: 100, ny: 40, averageCap: 100 +}, { + nx: 200, ny: 80, averageCap: 150 +}, { + nx: 400, ny: 160, averageCap: 300 +}, { + nx: 800, ny: 320, averageCap: 600 +}, { + nx: 1600, ny: 640, averageCap: 1200 +}, { + nx: 3200, ny: 1280, averageCap: 2400 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test heatmap | size:' + spec.nx + 'X' + spec.ny, function() { + 'use strict'; + + Plotly.register(PlotlyHeatmap); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var A = spec.nx; + var B = spec.ny; + spec.n = A * B; + + var x = Uint16Array.from({ length: A }, (_, i) => i); + var y = Uint16Array.from({ length: B }, (_, i) => i); + var z = []; + for(var k = 0; k < B ; k++) { + z[k] = Float64Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); + } + + var mock = { + data: [{ + type: 'heatmap', + x: x, + y: y, + z: z + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph heatmap traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + // console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.heatmaplayer'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js new file mode 100644 index 00000000000..814c1f3c381 --- /dev/null +++ b/test/jasmine/performance_tests/histogram_test.js @@ -0,0 +1,101 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyHistogram = require('../../../lib/histogram'); + +var gd = createGraphDiv(); + +var tests = [{ + n: 1000, averageCap: 75 +}, { + n: 2000, averageCap: 100 +}, { + n: 4000, averageCap: 150 +}, { + n: 8000, averageCap: 300 +}, { + n: 16000, averageCap: 600 +}, { + n: 32000, averageCap: 1200 +}, { + n: 64000, averageCap: 2400 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test histogram | size:' + spec.n, function() { + 'use strict'; + + Plotly.register(PlotlyHistogram); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var x = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'histogram', + x: x + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph histogram traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + // console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.trace.bars'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js new file mode 100644 index 00000000000..7e5a60eda72 --- /dev/null +++ b/test/jasmine/performance_tests/image_test.js @@ -0,0 +1,119 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyImage = require('../../../lib/image'); + +var gd = createGraphDiv(); + +var tests = [{ + nx: 50, ny: 20, averageCap: 75 +}, { + nx: 100, ny: 40, averageCap: 100 +}, { + nx: 200, ny: 80, averageCap: 150 +}, { + nx: 400, ny: 160, averageCap: 300 +}, { + nx: 800, ny: 320, averageCap: 600 +}, { + nx: 1600, ny: 640, averageCap: 1200 +}, { + nx: 3200, ny: 1280, averageCap: 2400 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test image | size:' + spec.nx + 'X' + spec.ny, function() { + 'use strict'; + + Plotly.register(PlotlyImage); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var A = spec.nx; + var B = spec.ny; + spec.n = A * B; + + var x = Uint16Array.from({ length: A }, (_, i) => i); + var y = Uint16Array.from({ length: B }, (_, i) => i); + var z = []; + for(var k = 0; k < B ; k++) { + z[k] = []; + for(var i = 0; i < A ; i++) { + z[k][i] = [ + Math.floor(127 * (1 + Math.cos(Math.sqrt(i)))), + 0, + Math.floor(127 * (1 + Math.cos(Math.sqrt(k)))), + ]; + } + } + + var mock = { + data: [{ + type: 'image', + x: x, + y: y, + z: z + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime; + + beforeEach(function(done) { + startTime = Date.now(); + + Plotly.newPlot(gd, mock).then(done); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + var maxDelta = 0; + var aveDelta = 0; + + samples.forEach(function(t) { + it('should graph image traces | turn: ' + t, function() { + var delta = Date.now() - startTime; + + if(t === 0) { + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t > 0) { // we skip the first run which is slow + maxDelta = Math.max(maxDelta, delta); + aveDelta += delta / nTimes; + } + + // console.log('turn: ' + t + ' | ' + delta + ' ms'); + + if(t === nTimes) { + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); + + expect(aveDelta).toBeLessThan(spec.averageCap); + } + + var nodes = d3SelectAll('g.imagelayer.mlayer'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 23634877680..741c134b75d 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -5,7 +5,7 @@ var Plotly = require('../../../lib/core'); var gd = createGraphDiv(); -[{ +var tests = [{ n: 1000, averageCap: 75 }, { n: 2000, averageCap: 100 @@ -19,11 +19,13 @@ var gd = createGraphDiv(); n: 32000, averageCap: 1200 }, { n: 64000, averageCap: 2400 -}].forEach(function(spec) { - describe('Bundle with scatter | size:' + spec.n, function() { +}]; + +tests.forEach(function(spec, index) { + describe('Performance test scatter | size:' + spec.n, function() { 'use strict'; - const samples = Array.from({ length: 5 }, (_, i) => i); + const samples = Array.from({ length: 9 }, (_, i) => i); const nTimes = samples.length - 1; var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); @@ -35,7 +37,7 @@ var gd = createGraphDiv(); y: y }], layout: { - width: 1200, + width: 900, height: 400 } }; @@ -60,27 +62,37 @@ var gd = createGraphDiv(); var delta = Date.now() - startTime; if(t === 0) { - console.log('________________________________'); - console.log('number of points in scatter: ' + spec.n); - console.log('expected average (cap): ' + spec.averageCap + ' ms'); + // console.log('________________________________'); + // console.log('number of points: ' + spec.n); + // console.log('expected average (cap): ' + spec.averageCap + ' ms'); + + tests[index].raw = []; } + tests[index].raw[t] = delta; if(t > 0) { // we skip the first run which is slow maxDelta = Math.max(maxDelta, delta); aveDelta += delta / nTimes; } - console.log('turn: ' + t + ' | ' + delta + ' ms'); + // console.log('turn: ' + t + ' | ' + delta + ' ms'); if(t === nTimes) { - console.log('max: ' + maxDelta); - console.log('ave: ' + aveDelta); + tests[index].average = aveDelta; + tests[index].maximum = maxDelta; + + // console.log('max: ' + maxDelta); + // console.log('ave: ' + aveDelta); expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.scatter'); expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + console.log(JSON.stringify(tests, null, 2)); + } }); }); }); From 0d9eb560d11000fb42c04b0413c77d29177c3f29 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 19 Jun 2025 18:57:02 -0400 Subject: [PATCH 03/45] skip testing against averageCap for now --- test/jasmine/performance_tests/bar_test.js | 2 +- test/jasmine/performance_tests/box_test.js | 2 +- test/jasmine/performance_tests/contour_test.js | 2 +- test/jasmine/performance_tests/heatmap_test.js | 2 +- test/jasmine/performance_tests/histogram_test.js | 2 +- test/jasmine/performance_tests/image_test.js | 2 +- test/jasmine/performance_tests/scatter_test.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 4276c4c3840..4e380917d86 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -86,7 +86,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.bars'); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 65e4ff374c0..cdfd388c563 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -87,7 +87,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.boxes'); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 00b4893fa62..d3d74e0085f 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -97,7 +97,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.contourlayer'); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index 454624bb716..51499809359 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -97,7 +97,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.heatmaplayer'); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 814c1f3c381..9a1328e7ed1 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -86,7 +86,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.bars'); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 7e5a60eda72..58ea002fd06 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -104,7 +104,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.imagelayer.mlayer'); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 741c134b75d..d81abe8b1a4 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -84,7 +84,7 @@ tests.forEach(function(spec, index) { // console.log('max: ' + maxDelta); // console.log('ave: ' + aveDelta); - expect(aveDelta).toBeLessThan(spec.averageCap); + // expect(aveDelta).toBeLessThan(spec.averageCap); } var nodes = d3SelectAll('g.trace.scatter'); From d7bf5b5bc0939edacdde33caa01107d872521cbd Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 19 Jun 2025 19:35:18 -0400 Subject: [PATCH 04/45] convert raw data to CSV --- .../performance_tests/assets/post_process.js | 15 +++++++++++++++ test/jasmine/performance_tests/bar_test.js | 3 +++ test/jasmine/performance_tests/box_test.js | 3 +++ test/jasmine/performance_tests/contour_test.js | 3 +++ test/jasmine/performance_tests/heatmap_test.js | 3 +++ test/jasmine/performance_tests/histogram_test.js | 3 +++ test/jasmine/performance_tests/image_test.js | 3 +++ test/jasmine/performance_tests/scatter_test.js | 3 +++ 8 files changed, 36 insertions(+) create mode 100644 test/jasmine/performance_tests/assets/post_process.js diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js new file mode 100644 index 00000000000..1512632bb45 --- /dev/null +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -0,0 +1,15 @@ +'use strict'; + +exports.writeRawDataAsCSV = function(traceName, allTests) { + for(var k = 0; k < allTests.length; k++) { + var test = allTests[k]; + + var str = traceName + ',' + test.n + '\n'; + str += 'id,time(ms)\n'; + for(var i = 0; i < test.raw.length; i++) { + str += i + ',' + test.raw[i] + '\n'; + } + + console.log(str); + } +}; diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 4e380917d86..7be47841da7 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBar = require('../../../lib/bar'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -94,6 +95,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('bar', tests); } }); }); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index cdfd388c563..9bf10dbeb20 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBox = require('../../../lib/box'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -95,6 +96,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('box', tests); } }); }); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index d3d74e0085f..5e53db58938 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyContour = require('../../../lib/contour'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -105,6 +106,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('contour', tests); } }); }); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index 51499809359..b23db01145d 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHeatmap = require('../../../lib/heatmap'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -105,6 +106,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('heatmap', tests); } }); }); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 9a1328e7ed1..bc3c936645d 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHistogram = require('../../../lib/histogram'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -94,6 +95,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('histogram', tests); } }); }); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 58ea002fd06..f388cebdcda 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyImage = require('../../../lib/image'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -112,6 +113,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('image', tests); } }); }); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index d81abe8b1a4..8e73308766f 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -2,6 +2,7 @@ var createGraphDiv = require('../assets/create_graph_div'); var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); @@ -92,6 +93,8 @@ tests.forEach(function(spec, index) { if(t === nTimes && index === tests.length - 1) { console.log(JSON.stringify(tests, null, 2)); + + writeRawDataAsCSV('scatter', tests); } }); }); From 9f607765cdd2fbe3a8d9e5cd9ae94745a7960244 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 20 Jun 2025 09:39:28 -0400 Subject: [PATCH 05/45] wait for actual rendering to complete --- test/jasmine/performance_tests/bar_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/box_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/contour_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/heatmap_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/histogram_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/image_test.js | 16 ++++++++++++---- test/jasmine/performance_tests/scatter_test.js | 16 ++++++++++++---- 7 files changed, 84 insertions(+), 28 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 7be47841da7..4b6ac713e99 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -45,12 +45,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -62,7 +70,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph bar traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 9bf10dbeb20..aa4d4d221dc 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -46,12 +46,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -63,7 +71,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph box traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 5e53db58938..722a0d0d95d 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -56,12 +56,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -73,7 +81,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph contour traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index b23db01145d..fc9d01d5be9 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -56,12 +56,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -73,7 +81,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph heatmap traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index bc3c936645d..b95d80cd4ac 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -45,12 +45,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -62,7 +70,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph histogram traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index f388cebdcda..73a3d9ea020 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -63,12 +63,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -80,7 +88,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph image traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 8e73308766f..a559b43b046 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -43,12 +43,20 @@ tests.forEach(function(spec, index) { } }; - var startTime; + var startTime, endTime; beforeEach(function(done) { - startTime = Date.now(); + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); - Plotly.newPlot(gd, mock).then(done); + Plotly.newPlot(gd, mock); }); afterEach(function(done) { @@ -60,7 +68,7 @@ tests.forEach(function(spec, index) { samples.forEach(function(t) { it('should graph scatter traces | turn: ' + t, function() { - var delta = Date.now() - startTime; + var delta = endTime - startTime; if(t === 0) { // console.log('________________________________'); From 12f73ad05098a32e8c2c8057fcc552ca7df84cc1 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 20 Jun 2025 10:38:13 -0400 Subject: [PATCH 06/45] download CSV file --- .../performance_tests/assets/post_process.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 1512632bb45..21dda96b62c 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,15 +1,27 @@ -'use strict'; - exports.writeRawDataAsCSV = function(traceName, allTests) { + var str = ''; for(var k = 0; k < allTests.length; k++) { var test = allTests[k]; - var str = traceName + ',' + test.n + '\n'; + str += traceName + ',' + test.n + '\n'; str += 'id,time(ms)\n'; for(var i = 0; i < test.raw.length; i++) { str += i + ',' + test.raw[i] + '\n'; } + str += '\n'; console.log(str); } + + // download a CSV file + var a = document.createElement('a'); + var myBlob = new Blob([str], {type: 'text/plain'}) + var url = window.URL.createObjectURL(myBlob); + a.href = url; + a.download = traceName + '.csv'; + a.style.display = 'none'; + document.body.append(a); + a.click(); + a.remove(); + window.URL.revokeObjectURL(url); }; From 2a4bc1ba9696e24a0eed44d390f8c7010e3e66f3 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 20 Jun 2025 11:24:11 -0400 Subject: [PATCH 07/45] revise CSV table --- test/jasmine/performance_tests/assets/post_process.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 21dda96b62c..898df5c8e94 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,18 +1,15 @@ exports.writeRawDataAsCSV = function(traceName, allTests) { - var str = ''; + var str = 'chart type,data points,run id,rendering time(ms)\n'; for(var k = 0; k < allTests.length; k++) { var test = allTests[k]; - str += traceName + ',' + test.n + '\n'; - str += 'id,time(ms)\n'; for(var i = 0; i < test.raw.length; i++) { - str += i + ',' + test.raw[i] + '\n'; + str += traceName + ',' + test.n + ',' + i + ',' + test.raw[i] + '\n'; } - str += '\n'; - - console.log(str); } + console.log(str); + // download a CSV file var a = document.createElement('a'); var myBlob = new Blob([str], {type: 'text/plain'}) From ba4327c38aa623a20b044eef2f9768ccbc4d54af Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 20 Jun 2025 11:26:59 -0400 Subject: [PATCH 08/45] store CSV --- .circleci/config.yml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index 6701dd7e259..6a1378f0800 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,6 +53,9 @@ jobs: - run: name: Run performance tests command: .circleci/test.sh performance-jasmine + - store_artifacts: + path: ~/Downloads + destination: / timezone-jasmine: From 855eaa2c82abb1ac60a397e9ff8b574cbab0e35f Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 20 Jun 2025 13:32:47 -0400 Subject: [PATCH 09/45] collect system info for performance tests --- .circleci/config.yml | 4 ++- package.json | 1 + tasks/system_info.js | 77 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) create mode 100644 tasks/system_info.js diff --git a/.circleci/config.yml b/.circleci/config.yml index 6a1378f0800..d79afdb0d98 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,11 +53,13 @@ jobs: - run: name: Run performance tests command: .circleci/test.sh performance-jasmine + - run: + name: Display system information + command: npm run system-info > ~/Downloads/system_info.txt - store_artifacts: path: ~/Downloads destination: / - timezone-jasmine: docker: # need '-browsers' version to test in real (xvfb-wrapped) browsers diff --git a/package.json b/package.json index 94dd2045e0d..9d5930a4030 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,7 @@ "test-syntax": "node tasks/test_syntax.js && npm run find-strings -- --no-output", "test-bundle": "node tasks/test_bundle.js", "test-performance": "node tasks/test_performance.js", + "system-info": "node tasks/system_info.js", "test-plain-obj": "node tasks/test_plain_obj.mjs", "test": "npm run test-jasmine -- --nowatch && npm run test-bundle && npm run test-image && npm run test-export && npm run test-syntax && npm run lint", "b64": "python3 test/image/generate_b64_mocks.py && node devtools/test_dashboard/server.mjs", diff --git a/tasks/system_info.js b/tasks/system_info.js new file mode 100644 index 00000000000..fd09c670100 --- /dev/null +++ b/tasks/system_info.js @@ -0,0 +1,77 @@ +var os = require('os'); + +var logs = []; +function addLog(str) { + logs.push(str) +} + +var systemInfo = { + platform: os.platform(), + type: os.type(), + arch: os.arch(), + release: os.release(), + version: os.version ? os.version() : 'Unknown', + hostname: os.hostname(), + homedir: os.homedir(), + tmpdir: os.tmpdir(), + endianness: os.endianness(), +}; + +addLog('💻 SYSTEM:'); +addLog(` Platform: ${systemInfo.platform}`); +addLog(` Type: ${systemInfo.type}`); +addLog(` Architecture: ${systemInfo.arch}`); +addLog(` Release: ${systemInfo.release}`); +addLog(` Hostname: ${systemInfo.hostname}`); + + +var cpus = os.cpus(); +var loadAvg = os.loadavg(); + +var cpuInfo = { + model: cpus[0].model, + speed: cpus[0].speed, + cores: cpus.length, + loadAverage: loadAvg, + cpuDetails: cpus +}; + +addLog(''); +addLog('🔧 CPU:'); +addLog(` Model: ${cpuInfo.model}`); +addLog(` Speed: ${cpuInfo.speed} MHz`); +addLog(` Cores: ${cpuInfo.cores}${cpuInfo.physicalCores ? ` (${cpuInfo.physicalCores} physical)` : ''}`); +addLog(` Load Average: ${loadAvg.map(load => load.toFixed(2)).join(', ')}`); + + +var totalMem = os.totalmem(); +var freeMem = os.freemem(); +var usedMem = totalMem - freeMem; + +var memoryInfo = { + total: totalMem, + free: freeMem, + used: usedMem, + usagePercent: (usedMem / totalMem) * 100 +}; + +function formatBytes(bytes, decimals = 2) { + if (bytes === 0) return '0 Bytes'; + if (!bytes) return 'Unknown'; + + var k = 1024; + var dm = decimals < 0 ? 0 : decimals; + var sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB']; + var i = Math.floor(Math.log(bytes) / Math.log(k)); + + return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i]; +} + +addLog(''); +addLog('💾 MEMORY:'); +addLog(` Total: ${formatBytes(memoryInfo.total)}`); +addLog(` Used: ${formatBytes(memoryInfo.used)} (${memoryInfo.usagePercent.toFixed(1)}%)`); +addLog(` Free: ${formatBytes(memoryInfo.free)}`); + + +console.log(logs.join('\n')); \ No newline at end of file From c46e7c61d8ce60a7d3fc414a31a02008a60e017f Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 10:02:18 -0400 Subject: [PATCH 10/45] combine all csv files --- .circleci/config.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.circleci/config.yml b/.circleci/config.yml index d79afdb0d98..c1362c052e4 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,6 +53,11 @@ jobs: - run: name: Run performance tests command: .circleci/test.sh performance-jasmine + - run: + name: Combine CSV files + command: | + head -n 1 `ls ~/Downloads/*.csv | head -n 1` > ~/Downloads/all.csv + tail -n+2 -q ~/Downloads/*.csv >> ~/Downloads/all.csv - run: name: Display system information command: npm run system-info > ~/Downloads/system_info.txt From 0e638144d376fe72abb88ccdfbd04c89c7f37382 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 10:06:14 -0400 Subject: [PATCH 11/45] do not display the JSON for now --- test/jasmine/performance_tests/bar_test.js | 2 +- test/jasmine/performance_tests/box_test.js | 2 +- test/jasmine/performance_tests/contour_test.js | 2 +- test/jasmine/performance_tests/heatmap_test.js | 2 +- test/jasmine/performance_tests/histogram_test.js | 2 +- test/jasmine/performance_tests/image_test.js | 2 +- test/jasmine/performance_tests/scatter_test.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 4b6ac713e99..486e2325596 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -102,7 +102,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('bar', tests); } diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index aa4d4d221dc..fe716b3d593 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -103,7 +103,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('box', tests); } diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 722a0d0d95d..853ebc66c39 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -113,7 +113,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('contour', tests); } diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index fc9d01d5be9..dd3eae8d89b 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -113,7 +113,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('heatmap', tests); } diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index b95d80cd4ac..05e0ad96edd 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -102,7 +102,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('histogram', tests); } diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 73a3d9ea020..73db9b89d58 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -120,7 +120,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('image', tests); } diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index a559b43b046..ec70e46ecc5 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -100,7 +100,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - console.log(JSON.stringify(tests, null, 2)); + // console.log(JSON.stringify(tests, null, 2)); writeRawDataAsCSV('scatter', tests); } From 5d2e5bb16432374dd177570ac90ec55e86679e29 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 10:15:18 -0400 Subject: [PATCH 12/45] simplify tests only keep raw results --- test/jasmine/performance_tests/bar_test.js | 40 ++++--------------- test/jasmine/performance_tests/box_test.js | 40 ++++--------------- .../jasmine/performance_tests/contour_test.js | 40 ++++--------------- .../jasmine/performance_tests/heatmap_test.js | 40 ++++--------------- .../performance_tests/histogram_test.js | 40 ++++--------------- test/jasmine/performance_tests/image_test.js | 40 ++++--------------- .../jasmine/performance_tests/scatter_test.js | 40 ++++--------------- 7 files changed, 49 insertions(+), 231 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 486e2325596..16d8a5a5b4b 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - n: 1000, averageCap: 75 + n: 1000 }, { - n: 2000, averageCap: 100 + n: 2000 }, { - n: 4000, averageCap: 150 + n: 4000 }, { - n: 8000, averageCap: 300 + n: 8000 }, { - n: 16000, averageCap: 600 + n: 16000 }, { - n: 32000, averageCap: 1200 + n: 32000 }, { - n: 64000, averageCap: 2400 + n: 64000 }]; tests.forEach(function(spec, index) { @@ -65,45 +65,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph bar traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.trace.bars'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('bar', tests); } }); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index fe716b3d593..2cfbf01f928 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - n: 1000, averageCap: 75 + n: 1000 }, { - n: 2000, averageCap: 100 + n: 2000 }, { - n: 4000, averageCap: 150 + n: 4000 }, { - n: 8000, averageCap: 300 + n: 8000 }, { - n: 16000, averageCap: 600 + n: 16000 }, { - n: 32000, averageCap: 1200 + n: 32000 }, { - n: 64000, averageCap: 2400 + n: 64000 }]; tests.forEach(function(spec, index) { @@ -66,45 +66,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph box traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.trace.boxes'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('box', tests); } }); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 853ebc66c39..b3a564320df 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - nx: 50, ny: 20, averageCap: 100 + nx: 50, ny: 20 }, { - nx: 100, ny: 40, averageCap: 125 + nx: 100, ny: 40 }, { - nx: 200, ny: 80, averageCap: 250 + nx: 200, ny: 80 }, { - nx: 400, ny: 160, averageCap: 500 + nx: 400, ny: 160 }, { - nx: 800, ny: 320, averageCap: 1000 + nx: 800, ny: 320 }, { - nx: 1600, ny: 640, averageCap: 2000 + nx: 1600, ny: 640 }, { - nx: 3200, ny: 1280, averageCap: 4000 + nx: 3200, ny: 1280 }]; tests.forEach(function(spec, index) { @@ -76,45 +76,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph contour traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.contourlayer'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('contour', tests); } }); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index dd3eae8d89b..e670025566e 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - nx: 50, ny: 20, averageCap: 75 + nx: 50, ny: 20 }, { - nx: 100, ny: 40, averageCap: 100 + nx: 100, ny: 40 }, { - nx: 200, ny: 80, averageCap: 150 + nx: 200, ny: 80 }, { - nx: 400, ny: 160, averageCap: 300 + nx: 400, ny: 160 }, { - nx: 800, ny: 320, averageCap: 600 + nx: 800, ny: 320 }, { - nx: 1600, ny: 640, averageCap: 1200 + nx: 1600, ny: 640 }, { - nx: 3200, ny: 1280, averageCap: 2400 + nx: 3200, ny: 1280 }]; tests.forEach(function(spec, index) { @@ -76,45 +76,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph heatmap traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.heatmaplayer'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('heatmap', tests); } }); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 05e0ad96edd..0ea1ad1ab33 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - n: 1000, averageCap: 75 + n: 1000 }, { - n: 2000, averageCap: 100 + n: 2000 }, { - n: 4000, averageCap: 150 + n: 4000 }, { - n: 8000, averageCap: 300 + n: 8000 }, { - n: 16000, averageCap: 600 + n: 16000 }, { - n: 32000, averageCap: 1200 + n: 32000 }, { - n: 64000, averageCap: 2400 + n: 64000 }]; tests.forEach(function(spec, index) { @@ -65,45 +65,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph histogram traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.trace.bars'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('histogram', tests); } }); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 73db9b89d58..456b65e4bfd 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -8,19 +8,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - nx: 50, ny: 20, averageCap: 75 + nx: 50, ny: 20 }, { - nx: 100, ny: 40, averageCap: 100 + nx: 100, ny: 40 }, { - nx: 200, ny: 80, averageCap: 150 + nx: 200, ny: 80 }, { - nx: 400, ny: 160, averageCap: 300 + nx: 400, ny: 160 }, { - nx: 800, ny: 320, averageCap: 600 + nx: 800, ny: 320 }, { - nx: 1600, ny: 640, averageCap: 1200 + nx: 1600, ny: 640 }, { - nx: 3200, ny: 1280, averageCap: 2400 + nx: 3200, ny: 1280 }]; tests.forEach(function(spec, index) { @@ -83,45 +83,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph image traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.imagelayer.mlayer'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('image', tests); } }); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index ec70e46ecc5..126ce3378dd 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -7,19 +7,19 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); var tests = [{ - n: 1000, averageCap: 75 + n: 1000 }, { - n: 2000, averageCap: 100 + n: 2000 }, { - n: 4000, averageCap: 150 + n: 4000 }, { - n: 8000, averageCap: 300 + n: 8000 }, { - n: 16000, averageCap: 600 + n: 16000 }, { - n: 32000, averageCap: 1200 + n: 32000 }, { - n: 64000, averageCap: 2400 + n: 64000 }]; tests.forEach(function(spec, index) { @@ -63,45 +63,19 @@ tests.forEach(function(spec, index) { delay(100)().then(done); }); - var maxDelta = 0; - var aveDelta = 0; - samples.forEach(function(t) { it('should graph scatter traces | turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { - // console.log('________________________________'); - // console.log('number of points: ' + spec.n); - // console.log('expected average (cap): ' + spec.averageCap + ' ms'); - tests[index].raw = []; } tests[index].raw[t] = delta; - if(t > 0) { // we skip the first run which is slow - maxDelta = Math.max(maxDelta, delta); - aveDelta += delta / nTimes; - } - - // console.log('turn: ' + t + ' | ' + delta + ' ms'); - - if(t === nTimes) { - tests[index].average = aveDelta; - tests[index].maximum = maxDelta; - - // console.log('max: ' + maxDelta); - // console.log('ave: ' + aveDelta); - - // expect(aveDelta).toBeLessThan(spec.averageCap); - } - var nodes = d3SelectAll('g.trace.scatter'); expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - // console.log(JSON.stringify(tests, null, 2)); - writeRawDataAsCSV('scatter', tests); } }); From 94b2fe039a2636d3db145eba2f1b37b03693b191 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 10:53:48 -0400 Subject: [PATCH 13/45] add violin tests --- test/jasmine/performance_tests/violin_test.js | 87 +++++++++++++++++++ 1 file changed, 87 insertions(+) create mode 100644 test/jasmine/performance_tests/violin_test.js diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js new file mode 100644 index 00000000000..bd8e7c11602 --- /dev/null +++ b/test/jasmine/performance_tests/violin_test.js @@ -0,0 +1,87 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/core'); +var PlotlyViolin = require('../../../lib/violin'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; + +var gd = createGraphDiv(); + +var tests = [{ + n: 1000 +}, { + n: 2000 +}, { + n: 4000 +}, { + n: 8000 +}, { + n: 16000 +}, { + n: 32000 +}, { + n: 64000 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test violin | size:' + spec.n, function() { + 'use strict'; + + Plotly.register(PlotlyViolin); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'violin', + points: 'all', + y: y + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime, endTime; + + beforeEach(function(done) { + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); + + Plotly.newPlot(gd, mock); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + samples.forEach(function(t) { + it('should graph violin traces | turn: ' + t, function() { + var delta = endTime - startTime; + + if(t === 0) { + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + var nodes = d3SelectAll('g.trace.violins'); + expect(nodes.size()).toEqual(1); + + if(t === nTimes && index === tests.length - 1) { + writeRawDataAsCSV('violin', tests); + } + }); + }); + }); +}); From b532cb0457118dbda673fb5dd9c5d4174e58403f Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 11:03:07 -0400 Subject: [PATCH 14/45] add scattergl tests --- .../performance_tests/scattergl_test.js | 91 +++++++++++++++++++ 1 file changed, 91 insertions(+) create mode 100644 test/jasmine/performance_tests/scattergl_test.js diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js new file mode 100644 index 00000000000..fd899919a9b --- /dev/null +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -0,0 +1,91 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var Plotly = require('../../../lib/core'); +var PlotlyScattergl = require('../../../lib/scattergl'); +var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; + +var gd = createGraphDiv(); + +var tests = [{ + n: 1000 +}, { + n: 2000 +}, { + n: 4000 +}, { + n: 8000 +}, { + n: 16000 +}, { + n: 32000 +}, { + n: 64000 +}, { + n: 128000 +}, { + n: 256000 +}, { + n: 512000 +}, { + n: 1024000 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test scattergl | size:' + spec.n, function() { + 'use strict'; + + Plotly.register(PlotlyScattergl); + + const samples = Array.from({ length: 9 }, (_, i) => i); + const nTimes = samples.length - 1; + + var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + + var mock = { + data: [{ + type: 'scattergl', + mode: 'markers', + y: y + }], + layout: { + width: 900, + height: 400 + } + }; + + var startTime, endTime; + + beforeEach(function(done) { + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); + + Plotly.newPlot(gd, mock); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + samples.forEach(function(t) { + it('should graph scattergl traces | turn: ' + t, function() { + var delta = endTime - startTime; + + if(t === 0) { + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t === nTimes && index === tests.length - 1) { + writeRawDataAsCSV('scattergl', tests); + } + }); + }); + }); +}); From ef345ef055e9a6fa2477f59cedc8fe0d557e6a27 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 11:19:02 -0400 Subject: [PATCH 15/45] refactor tests --- test/jasmine/performance_tests/bar_test.js | 10 +++++----- test/jasmine/performance_tests/box_test.js | 10 +++++----- test/jasmine/performance_tests/contour_test.js | 10 +++++----- test/jasmine/performance_tests/heatmap_test.js | 10 +++++----- test/jasmine/performance_tests/histogram_test.js | 10 +++++----- test/jasmine/performance_tests/image_test.js | 7 +++++-- test/jasmine/performance_tests/scatter_test.js | 6 +++--- test/jasmine/performance_tests/scattergl_test.js | 10 +++++----- test/jasmine/performance_tests/violin_test.js | 10 +++++----- 9 files changed, 43 insertions(+), 40 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 16d8a5a5b4b..d455357f6c4 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyBar = require('../../../lib/bar'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyBar); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test bar | size:' + spec.n, function() { 'use strict'; - Plotly.register(PlotlyBar); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 2cfbf01f928..6caf60b5afe 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyBox = require('../../../lib/box'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyBox); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test box | size:' + spec.n, function() { 'use strict'; - Plotly.register(PlotlyBox); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index b3a564320df..3a7cff40f8f 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyContour = require('../../../lib/contour'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyContour); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ nx: 50, ny: 20 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test contour | size:' + spec.nx + 'X' + spec.ny, function() { 'use strict'; - Plotly.register(PlotlyContour); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var A = spec.nx; var B = spec.ny; spec.n = A * B; diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index e670025566e..a28a7d19455 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyHeatmap = require('../../../lib/heatmap'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyHeatmap); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ nx: 50, ny: 20 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test heatmap | size:' + spec.nx + 'X' + spec.ny, function() { 'use strict'; - Plotly.register(PlotlyHeatmap); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var A = spec.nx; var B = spec.ny; spec.n = A * B; diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 0ea1ad1ab33..0685187e813 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyHistogram = require('../../../lib/histogram'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyHistogram); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test histogram | size:' + spec.n, function() { 'use strict'; - Plotly.register(PlotlyHistogram); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var x = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 456b65e4bfd..f4fd2e09732 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyImage = require('../../../lib/image'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyImage); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ nx: 50, ny: 20 }, { @@ -27,8 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test image | size:' + spec.nx + 'X' + spec.ny, function() { 'use strict'; - Plotly.register(PlotlyImage); - const samples = Array.from({ length: 9 }, (_, i) => i); const nTimes = samples.length - 1; diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 126ce3378dd..4b5b69436e5 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -6,6 +6,9 @@ var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -26,9 +29,6 @@ tests.forEach(function(spec, index) { describe('Performance test scatter | size:' + spec.n, function() { 'use strict'; - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index fd899919a9b..41aa84a5abc 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -4,8 +4,13 @@ var Plotly = require('../../../lib/core'); var PlotlyScattergl = require('../../../lib/scattergl'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyScattergl); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -34,11 +39,6 @@ tests.forEach(function(spec, index) { describe('Performance test scattergl | size:' + spec.n, function() { 'use strict'; - Plotly.register(PlotlyScattergl); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index bd8e7c11602..3aa96a80ffc 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -5,8 +5,13 @@ var Plotly = require('../../../lib/core'); var PlotlyViolin = require('../../../lib/violin'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +Plotly.register(PlotlyViolin); + var gd = createGraphDiv(); +const samples = Array.from({ length: 9 }, (_, i) => i); +const nTimes = samples.length - 1; + var tests = [{ n: 1000 }, { @@ -27,11 +32,6 @@ tests.forEach(function(spec, index) { describe('Performance test violin | size:' + spec.n, function() { 'use strict'; - Plotly.register(PlotlyViolin); - - const samples = Array.from({ length: 9 }, (_, i) => i); - const nTimes = samples.length - 1; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); var mock = { From 33620b72dcd720c9930181f0bef60dcc2345aa29 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 12:24:52 -0400 Subject: [PATCH 16/45] revisit tests --- .../performance_tests/assets/constants.js | 5 + .../performance_tests/assets/post_process.js | 8 +- test/jasmine/performance_tests/bar_test.js | 3 +- test/jasmine/performance_tests/box_test.js | 3 +- .../jasmine/performance_tests/contour_test.js | 3 +- .../jasmine/performance_tests/heatmap_test.js | 3 +- .../performance_tests/histogram_test.js | 3 +- test/jasmine/performance_tests/image_test.js | 5 +- .../jasmine/performance_tests/scatter_test.js | 124 ++++++++++++++---- .../performance_tests/scattergl_test.js | 3 +- test/jasmine/performance_tests/violin_test.js | 3 +- 11 files changed, 129 insertions(+), 34 deletions(-) create mode 100644 test/jasmine/performance_tests/assets/constants.js diff --git a/test/jasmine/performance_tests/assets/constants.js b/test/jasmine/performance_tests/assets/constants.js new file mode 100644 index 00000000000..53fb3438b71 --- /dev/null +++ b/test/jasmine/performance_tests/assets/constants.js @@ -0,0 +1,5 @@ +'use strict'; + +module.exports = { + nSamples: 1 +}; diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 898df5c8e94..fc98c49d9bb 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,10 +1,14 @@ exports.writeRawDataAsCSV = function(traceName, allTests) { - var str = 'chart type,data points,run id,rendering time(ms)\n'; + var str = 'number of traces,chart type,data points,run id,rendering time(ms)\n'; for(var k = 0; k < allTests.length; k++) { var test = allTests[k]; for(var i = 0; i < test.raw.length; i++) { - str += traceName + ',' + test.n + ',' + i + ',' + test.raw[i] + '\n'; + str += + (test.nTraces || 1) + ',' + + (traceName + (test.mode ? '_' + test.mode : '')) + ',' + + test.n + ',' + i + ',' + + test.raw[i] + '\n'; } } diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index d455357f6c4..a86c30d66d6 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBar = require('../../../lib/bar'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyBar); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 6caf60b5afe..3a0444cec36 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBox = require('../../../lib/box'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyBox); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 3a7cff40f8f..624f5743454 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyContour = require('../../../lib/contour'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyContour); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index a28a7d19455..ef95a05627d 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHeatmap = require('../../../lib/heatmap'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyHeatmap); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 0685187e813..8d38d23852d 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHistogram = require('../../../lib/histogram'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyHistogram); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index f4fd2e09732..12171dccbd7 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyImage = require('../../../lib/image'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyImage); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ @@ -32,7 +33,7 @@ tests.forEach(function(spec, index) { describe('Performance test image | size:' + spec.nx + 'X' + spec.ny, function() { 'use strict'; - const samples = Array.from({ length: 9 }, (_, i) => i); + const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var A = spec.nx; diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 4b5b69436e5..24deb2d3ab1 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -3,49 +3,127 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'markers', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'markers', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'markers', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'markers', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'markers', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'markers', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'markers', nTraces: 1 +}, { + n: 1000, mode: 'lines', nTraces: 1 +}, { + n: 2000, mode: 'lines', nTraces: 1 +}, { + n: 4000, mode: 'lines', nTraces: 1 +}, { + n: 8000, mode: 'lines', nTraces: 1 +}, { + n: 16000, mode: 'lines', nTraces: 1 +}, { + n: 32000, mode: 'lines', nTraces: 1 +}, { + n: 64000, mode: 'lines', nTraces: 1 +}, { + n: 1000, mode: 'markers', nTraces: 10 +}, { + n: 2000, mode: 'markers', nTraces: 10 +}, { + n: 4000, mode: 'markers', nTraces: 10 +}, { + n: 8000, mode: 'markers', nTraces: 10 +}, { + n: 16000, mode: 'markers', nTraces: 10 +}, { + n: 32000, mode: 'markers', nTraces: 10 +}, { + n: 64000, mode: 'markers', nTraces: 10 +}, { + n: 1000, mode: 'lines', nTraces: 10 +}, { + n: 2000, mode: 'lines', nTraces: 10 +}, { + n: 4000, mode: 'lines', nTraces: 10 +}, { + n: 8000, mode: 'lines', nTraces: 10 +}, { + n: 16000, mode: 'lines', nTraces: 10 +}, { + n: 32000, mode: 'lines', nTraces: 10 +}, { + n: 64000, mode: 'lines', nTraces: 10 +}, { + n: 1000, mode: 'markers', nTraces: 100 +}, { + n: 2000, mode: 'markers', nTraces: 100 +}, { + n: 4000, mode: 'markers', nTraces: 100 +}, { + n: 8000, mode: 'markers', nTraces: 100 +}, { + n: 16000, mode: 'markers', nTraces: 100 +}, { + n: 32000, mode: 'markers', nTraces: 100 +}, { + n: 64000, mode: 'markers', nTraces: 100 +}, { + n: 1000, mode: 'lines', nTraces: 100 +}, { + n: 2000, mode: 'lines', nTraces: 100 +}, { + n: 4000, mode: 'lines', nTraces: 100 +}, { + n: 8000, mode: 'lines', nTraces: 100 +}, { + n: 16000, mode: 'lines', nTraces: 100 +}, { + n: 32000, mode: 'lines', nTraces: 100 +}, { + n: 64000, mode: 'lines', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test scatter | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'scatter | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var startTime, endTime; - var mock = { - data: [{ - type: 'scatter', - mode: 'markers', - y: y - }], - layout: { - width: 900, - height: 400 + beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'scatter', + mode: spec.mode, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => i + k * nPerTrace) + }); } - }; - var startTime, endTime; + var mock = { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; - beforeEach(function(done) { startTime = performance.now(); // Wait for actual rendering to complete @@ -73,7 +151,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; var nodes = d3SelectAll('g.trace.scatter'); - expect(nodes.size()).toEqual(1); + expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { writeRawDataAsCSV('scatter', tests); diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index 41aa84a5abc..1cbc97e9cfe 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -3,12 +3,13 @@ var delay = require('../assets/delay'); var Plotly = require('../../../lib/core'); var PlotlyScattergl = require('../../../lib/scattergl'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyScattergl); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index 3aa96a80ffc..5b56f2b8bbd 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -4,12 +4,13 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyViolin = require('../../../lib/violin'); var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyViolin); var gd = createGraphDiv(); -const samples = Array.from({ length: 9 }, (_, i) => i); +const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ From b6dac795bbff219dc4677586a023311472822085 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 12:42:37 -0400 Subject: [PATCH 17/45] extend scattergl --- .../performance_tests/scattergl_test.js | 119 ++++++++++++++---- 1 file changed, 94 insertions(+), 25 deletions(-) diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index 1cbc97e9cfe..55c0aa6bf5c 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -13,50 +13,119 @@ const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'markers', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'markers', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'markers', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'markers', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'markers', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'markers', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'markers', nTraces: 1 }, { - n: 128000 + n: 1000, mode: 'lines', nTraces: 1 }, { - n: 256000 + n: 2000, mode: 'lines', nTraces: 1 }, { - n: 512000 + n: 4000, mode: 'lines', nTraces: 1 }, { - n: 1024000 + n: 8000, mode: 'lines', nTraces: 1 +}, { + n: 16000, mode: 'lines', nTraces: 1 +}, { + n: 32000, mode: 'lines', nTraces: 1 +}, { + n: 64000, mode: 'lines', nTraces: 1 +}, { + n: 1000, mode: 'markers', nTraces: 10 +}, { + n: 2000, mode: 'markers', nTraces: 10 +}, { + n: 4000, mode: 'markers', nTraces: 10 +}, { + n: 8000, mode: 'markers', nTraces: 10 +}, { + n: 16000, mode: 'markers', nTraces: 10 +}, { + n: 32000, mode: 'markers', nTraces: 10 +}, { + n: 64000, mode: 'markers', nTraces: 10 +}, { + n: 1000, mode: 'lines', nTraces: 10 +}, { + n: 2000, mode: 'lines', nTraces: 10 +}, { + n: 4000, mode: 'lines', nTraces: 10 +}, { + n: 8000, mode: 'lines', nTraces: 10 +}, { + n: 16000, mode: 'lines', nTraces: 10 +}, { + n: 32000, mode: 'lines', nTraces: 10 +}, { + n: 64000, mode: 'lines', nTraces: 10 +}, { + n: 1000, mode: 'markers', nTraces: 100 +}, { + n: 2000, mode: 'markers', nTraces: 100 +}, { + n: 4000, mode: 'markers', nTraces: 100 +}, { + n: 8000, mode: 'markers', nTraces: 100 +}, { + n: 16000, mode: 'markers', nTraces: 100 +}, { + n: 32000, mode: 'markers', nTraces: 100 +}, { + n: 64000, mode: 'markers', nTraces: 100 +}, { + n: 1000, mode: 'lines', nTraces: 100 +}, { + n: 2000, mode: 'lines', nTraces: 100 +}, { + n: 4000, mode: 'lines', nTraces: 100 +}, { + n: 8000, mode: 'lines', nTraces: 100 +}, { + n: 16000, mode: 'lines', nTraces: 100 +}, { + n: 32000, mode: 'lines', nTraces: 100 +}, { + n: 64000, mode: 'lines', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test scattergl | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'scattergl | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var startTime, endTime; - var mock = { - data: [{ - type: 'scattergl', - mode: 'markers', - y: y - }], - layout: { - width: 900, - height: 400 + beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'scattergl', + mode: spec.mode, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => i + k * nPerTrace) + }); } - }; - var startTime, endTime; + var mock = { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; - beforeEach(function(done) { startTime = performance.now(); // Wait for actual rendering to complete From 543478e7fbaedc56a9da21c4d435859d20b4ce62 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 13:01:22 -0400 Subject: [PATCH 18/45] extend bar --- test/jasmine/performance_tests/bar_test.js | 120 +++++++++++++++++---- 1 file changed, 99 insertions(+), 21 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index a86c30d66d6..a45716a1a09 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -14,41 +14,119 @@ const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'group', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'group', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'group', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'group', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'group', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'group', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'group', nTraces: 1 +}, { + n: 1000, mode: 'stack', nTraces: 1 +}, { + n: 2000, mode: 'stack', nTraces: 1 +}, { + n: 4000, mode: 'stack', nTraces: 1 +}, { + n: 8000, mode: 'stack', nTraces: 1 +}, { + n: 16000, mode: 'stack', nTraces: 1 +}, { + n: 32000, mode: 'stack', nTraces: 1 +}, { + n: 64000, mode: 'stack', nTraces: 1 +}, { + n: 1000, mode: 'group', nTraces: 10 +}, { + n: 2000, mode: 'group', nTraces: 10 +}, { + n: 4000, mode: 'group', nTraces: 10 +}, { + n: 8000, mode: 'group', nTraces: 10 +}, { + n: 16000, mode: 'group', nTraces: 10 +}, { + n: 32000, mode: 'group', nTraces: 10 +}, { + n: 64000, mode: 'group', nTraces: 10 +}, { + n: 1000, mode: 'stack', nTraces: 10 +}, { + n: 2000, mode: 'stack', nTraces: 10 +}, { + n: 4000, mode: 'stack', nTraces: 10 +}, { + n: 8000, mode: 'stack', nTraces: 10 +}, { + n: 16000, mode: 'stack', nTraces: 10 +}, { + n: 32000, mode: 'stack', nTraces: 10 +}, { + n: 64000, mode: 'stack', nTraces: 10 +}, { + n: 1000, mode: 'group', nTraces: 100 +}, { + n: 2000, mode: 'group', nTraces: 100 +}, { + n: 4000, mode: 'group', nTraces: 100 +}, { + n: 8000, mode: 'group', nTraces: 100 +}, { + n: 16000, mode: 'group', nTraces: 100 +}, { + n: 32000, mode: 'group', nTraces: 100 +}, { + n: 64000, mode: 'group', nTraces: 100 +}, { + n: 1000, mode: 'stack', nTraces: 100 +}, { + n: 2000, mode: 'stack', nTraces: 100 +}, { + n: 4000, mode: 'stack', nTraces: 100 +}, { + n: 8000, mode: 'stack', nTraces: 100 +}, { + n: 16000, mode: 'stack', nTraces: 100 +}, { + n: 32000, mode: 'stack', nTraces: 100 +}, { + n: 64000, mode: 'stack', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test bar | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'bar | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var startTime, endTime; - var mock = { - data: [{ - type: 'bar', - y: y - }], - layout: { - width: 900, - height: 400 + beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'bar', + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => i) + }); } - }; - var startTime, endTime; + var mock = { + data: data, + layout: { + barmode: spec.mode, + showlegend: false, + width: 900, + height: 400 + } + }; - beforeEach(function(done) { startTime = performance.now(); // Wait for actual rendering to complete @@ -76,7 +154,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; var nodes = d3SelectAll('g.trace.bars'); - expect(nodes.size()).toEqual(1); + expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { writeRawDataAsCSV('bar', tests); From ff93b2edd7d174be5998ef59761b2f52a1e7966d Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 13:09:55 -0400 Subject: [PATCH 19/45] extend box --- test/jasmine/performance_tests/box_test.js | 123 +++++++++++++++++---- 1 file changed, 100 insertions(+), 23 deletions(-) diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 3a0444cec36..35d64d43a5f 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -14,42 +14,119 @@ const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'no points', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'no points', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'no points', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'no points', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'no points', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'no points', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'no points', nTraces: 1 +}, { + n: 1000, mode: 'all points', nTraces: 1 +}, { + n: 2000, mode: 'all points', nTraces: 1 +}, { + n: 4000, mode: 'all points', nTraces: 1 +}, { + n: 8000, mode: 'all points', nTraces: 1 +}, { + n: 16000, mode: 'all points', nTraces: 1 +}, { + n: 32000, mode: 'all points', nTraces: 1 +}, { + n: 64000, mode: 'all points', nTraces: 1 +}, { + n: 1000, mode: 'no points', nTraces: 10 +}, { + n: 2000, mode: 'no points', nTraces: 10 +}, { + n: 4000, mode: 'no points', nTraces: 10 +}, { + n: 8000, mode: 'no points', nTraces: 10 +}, { + n: 16000, mode: 'no points', nTraces: 10 +}, { + n: 32000, mode: 'no points', nTraces: 10 +}, { + n: 64000, mode: 'no points', nTraces: 10 +}, { + n: 1000, mode: 'all points', nTraces: 10 +}, { + n: 2000, mode: 'all points', nTraces: 10 +}, { + n: 4000, mode: 'all points', nTraces: 10 +}, { + n: 8000, mode: 'all points', nTraces: 10 +}, { + n: 16000, mode: 'all points', nTraces: 10 +}, { + n: 32000, mode: 'all points', nTraces: 10 +}, { + n: 64000, mode: 'all points', nTraces: 10 +}, { + n: 1000, mode: 'no points', nTraces: 100 +}, { + n: 2000, mode: 'no points', nTraces: 100 +}, { + n: 4000, mode: 'no points', nTraces: 100 +}, { + n: 8000, mode: 'no points', nTraces: 100 +}, { + n: 16000, mode: 'no points', nTraces: 100 +}, { + n: 32000, mode: 'no points', nTraces: 100 +}, { + n: 64000, mode: 'no points', nTraces: 100 +}, { + n: 1000, mode: 'all points', nTraces: 100 +}, { + n: 2000, mode: 'all points', nTraces: 100 +}, { + n: 4000, mode: 'all points', nTraces: 100 +}, { + n: 8000, mode: 'all points', nTraces: 100 +}, { + n: 16000, mode: 'all points', nTraces: 100 +}, { + n: 32000, mode: 'all points', nTraces: 100 +}, { + n: 64000, mode: 'all points', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test box | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'box | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - - var mock = { - data: [{ - type: 'box', - boxpoints: 'all', - y: y - }], - layout: { - width: 900, - height: 400 - } - }; - var startTime, endTime; beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'box', + boxpoints: spec.mode === 'all points' ? 'all' : false, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => k) + }); + } + + var mock = { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; + startTime = performance.now(); // Wait for actual rendering to complete @@ -77,7 +154,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; var nodes = d3SelectAll('g.trace.boxes'); - expect(nodes.size()).toEqual(1); + expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { writeRawDataAsCSV('box', tests); From e3cd7b5dd8a6f4c684f24447da546b1ca5d9aba3 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 13:12:32 -0400 Subject: [PATCH 20/45] extend violin --- test/jasmine/performance_tests/violin_test.js | 123 ++++++++++++++---- 1 file changed, 100 insertions(+), 23 deletions(-) diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index 5b56f2b8bbd..9c53a1deca1 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -14,42 +14,119 @@ const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'no points', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'no points', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'no points', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'no points', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'no points', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'no points', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'no points', nTraces: 1 +}, { + n: 1000, mode: 'all points', nTraces: 1 +}, { + n: 2000, mode: 'all points', nTraces: 1 +}, { + n: 4000, mode: 'all points', nTraces: 1 +}, { + n: 8000, mode: 'all points', nTraces: 1 +}, { + n: 16000, mode: 'all points', nTraces: 1 +}, { + n: 32000, mode: 'all points', nTraces: 1 +}, { + n: 64000, mode: 'all points', nTraces: 1 +}, { + n: 1000, mode: 'no points', nTraces: 10 +}, { + n: 2000, mode: 'no points', nTraces: 10 +}, { + n: 4000, mode: 'no points', nTraces: 10 +}, { + n: 8000, mode: 'no points', nTraces: 10 +}, { + n: 16000, mode: 'no points', nTraces: 10 +}, { + n: 32000, mode: 'no points', nTraces: 10 +}, { + n: 64000, mode: 'no points', nTraces: 10 +}, { + n: 1000, mode: 'all points', nTraces: 10 +}, { + n: 2000, mode: 'all points', nTraces: 10 +}, { + n: 4000, mode: 'all points', nTraces: 10 +}, { + n: 8000, mode: 'all points', nTraces: 10 +}, { + n: 16000, mode: 'all points', nTraces: 10 +}, { + n: 32000, mode: 'all points', nTraces: 10 +}, { + n: 64000, mode: 'all points', nTraces: 10 +}, { + n: 1000, mode: 'no points', nTraces: 100 +}, { + n: 2000, mode: 'no points', nTraces: 100 +}, { + n: 4000, mode: 'no points', nTraces: 100 +}, { + n: 8000, mode: 'no points', nTraces: 100 +}, { + n: 16000, mode: 'no points', nTraces: 100 +}, { + n: 32000, mode: 'no points', nTraces: 100 +}, { + n: 64000, mode: 'no points', nTraces: 100 +}, { + n: 1000, mode: 'all points', nTraces: 100 +}, { + n: 2000, mode: 'all points', nTraces: 100 +}, { + n: 4000, mode: 'all points', nTraces: 100 +}, { + n: 8000, mode: 'all points', nTraces: 100 +}, { + n: 16000, mode: 'all points', nTraces: 100 +}, { + n: 32000, mode: 'all points', nTraces: 100 +}, { + n: 64000, mode: 'all points', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test violin | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'violin | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var y = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - - var mock = { - data: [{ - type: 'violin', - points: 'all', - y: y - }], - layout: { - width: 900, - height: 400 - } - }; - var startTime, endTime; beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'violin', + points: spec.mode === 'all points' ? 'all' : false, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => k) + }); + } + + var mock = { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; + startTime = performance.now(); // Wait for actual rendering to complete @@ -77,7 +154,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; var nodes = d3SelectAll('g.trace.violins'); - expect(nodes.size()).toEqual(1); + expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { writeRawDataAsCSV('violin', tests); From 0b0642ac82368e9c1d044df4376d87a98fc2281e Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 13:15:55 -0400 Subject: [PATCH 21/45] extend histogram --- .../performance_tests/histogram_test.js | 120 +++++++++++++++--- 1 file changed, 99 insertions(+), 21 deletions(-) diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 8d38d23852d..81b5986dca2 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -14,41 +14,119 @@ const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; var tests = [{ - n: 1000 + n: 1000, mode: 'group', nTraces: 1 }, { - n: 2000 + n: 2000, mode: 'group', nTraces: 1 }, { - n: 4000 + n: 4000, mode: 'group', nTraces: 1 }, { - n: 8000 + n: 8000, mode: 'group', nTraces: 1 }, { - n: 16000 + n: 16000, mode: 'group', nTraces: 1 }, { - n: 32000 + n: 32000, mode: 'group', nTraces: 1 }, { - n: 64000 + n: 64000, mode: 'group', nTraces: 1 +}, { + n: 1000, mode: 'stack', nTraces: 1 +}, { + n: 2000, mode: 'stack', nTraces: 1 +}, { + n: 4000, mode: 'stack', nTraces: 1 +}, { + n: 8000, mode: 'stack', nTraces: 1 +}, { + n: 16000, mode: 'stack', nTraces: 1 +}, { + n: 32000, mode: 'stack', nTraces: 1 +}, { + n: 64000, mode: 'stack', nTraces: 1 +}, { + n: 1000, mode: 'group', nTraces: 10 +}, { + n: 2000, mode: 'group', nTraces: 10 +}, { + n: 4000, mode: 'group', nTraces: 10 +}, { + n: 8000, mode: 'group', nTraces: 10 +}, { + n: 16000, mode: 'group', nTraces: 10 +}, { + n: 32000, mode: 'group', nTraces: 10 +}, { + n: 64000, mode: 'group', nTraces: 10 +}, { + n: 1000, mode: 'stack', nTraces: 10 +}, { + n: 2000, mode: 'stack', nTraces: 10 +}, { + n: 4000, mode: 'stack', nTraces: 10 +}, { + n: 8000, mode: 'stack', nTraces: 10 +}, { + n: 16000, mode: 'stack', nTraces: 10 +}, { + n: 32000, mode: 'stack', nTraces: 10 +}, { + n: 64000, mode: 'stack', nTraces: 10 +}, { + n: 1000, mode: 'group', nTraces: 100 +}, { + n: 2000, mode: 'group', nTraces: 100 +}, { + n: 4000, mode: 'group', nTraces: 100 +}, { + n: 8000, mode: 'group', nTraces: 100 +}, { + n: 16000, mode: 'group', nTraces: 100 +}, { + n: 32000, mode: 'group', nTraces: 100 +}, { + n: 64000, mode: 'group', nTraces: 100 +}, { + n: 1000, mode: 'stack', nTraces: 100 +}, { + n: 2000, mode: 'stack', nTraces: 100 +}, { + n: 4000, mode: 'stack', nTraces: 100 +}, { + n: 8000, mode: 'stack', nTraces: 100 +}, { + n: 16000, mode: 'stack', nTraces: 100 +}, { + n: 32000, mode: 'stack', nTraces: 100 +}, { + n: 64000, mode: 'stack', nTraces: 100 }]; tests.forEach(function(spec, index) { - describe('Performance test histogram | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + 'histogram | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; - var x = Float64Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var startTime, endTime; - var mock = { - data: [{ - type: 'histogram', - x: x - }], - layout: { - width: 900, - height: 400 + beforeEach(function(done) { + var z = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'histogram', + x: z.slice(k * nPerTrace, (k + 1) * nPerTrace), + y: Array.from({ length: nPerTrace }, (_, i) => i) + }); } - }; - var startTime, endTime; + var mock = { + data: data, + layout: { + barmode: spec.mode, + showlegend: false, + width: 900, + height: 400 + } + }; - beforeEach(function(done) { startTime = performance.now(); // Wait for actual rendering to complete @@ -76,7 +154,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; var nodes = d3SelectAll('g.trace.bars'); - expect(nodes.size()).toEqual(1); + expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { writeRawDataAsCSV('histogram', tests); From 1227e2a07730c878031f7207cd001773fb96a3d1 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:07:20 -0400 Subject: [PATCH 22/45] revise download csv --- .../performance_tests/assets/post_process.js | 26 ++++++++++++------- test/jasmine/performance_tests/bar_test.js | 4 +-- test/jasmine/performance_tests/box_test.js | 4 +-- .../jasmine/performance_tests/contour_test.js | 4 +-- .../jasmine/performance_tests/heatmap_test.js | 4 +-- .../performance_tests/histogram_test.js | 4 +-- test/jasmine/performance_tests/image_test.js | 4 +-- .../jasmine/performance_tests/scatter_test.js | 4 +-- .../performance_tests/scattergl_test.js | 4 +-- test/jasmine/performance_tests/violin_test.js | 4 +-- 10 files changed, 34 insertions(+), 28 deletions(-) diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index fc98c49d9bb..5172d0eb1db 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,20 +1,26 @@ -exports.writeRawDataAsCSV = function(traceName, allTests) { - var str = 'number of traces,chart type,data points,run id,rendering time(ms)\n'; +exports.downloadCSV = function(traceName, allTests) { + var str = [ + 'number of traces', + 'chart type', + 'data points', + 'run id', + 'rendering time(ms)' + ].join(',') + '\n'; for(var k = 0; k < allTests.length; k++) { var test = allTests[k]; for(var i = 0; i < test.raw.length; i++) { - str += - (test.nTraces || 1) + ',' + - (traceName + (test.mode ? '_' + test.mode : '')) + ',' + - test.n + ',' + i + ',' + - test.raw[i] + '\n'; + str += [ + (test.nTraces || 1), + (traceName + (test.mode ? ' ' + test.mode : '')), + test.n, + i, + test.raw[i] + ].join(',') + '\n'; } } - console.log(str); - - // download a CSV file + // download file by browser var a = document.createElement('a'); var myBlob = new Blob([str], {type: 'text/plain'}) var url = window.URL.createObjectURL(myBlob); diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index a45716a1a09..9edca9ec1b9 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBar = require('../../../lib/bar'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyBar); @@ -157,7 +157,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('bar', tests); + downloadCSV('bar', tests); } }); }); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 35d64d43a5f..e5a7bae6678 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyBox = require('../../../lib/box'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyBox); @@ -157,7 +157,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('box', tests); + downloadCSV('box', tests); } }); }); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 624f5743454..c38e1722b02 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyContour = require('../../../lib/contour'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyContour); @@ -90,7 +90,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('contour', tests); + downloadCSV('contour', tests); } }); }); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index ef95a05627d..0c0ae151e77 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHeatmap = require('../../../lib/heatmap'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyHeatmap); @@ -90,7 +90,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('heatmap', tests); + downloadCSV('heatmap', tests); } }); }); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index 81b5986dca2..ccf3e75782f 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyHistogram = require('../../../lib/histogram'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyHistogram); @@ -157,7 +157,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('histogram', tests); + downloadCSV('histogram', tests); } }); }); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 12171dccbd7..39ddf256477 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyImage = require('../../../lib/image'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyImage); @@ -100,7 +100,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(1); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('image', tests); + downloadCSV('image', tests); } }); }); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 24deb2d3ab1..c08425a87ee 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -2,7 +2,7 @@ var createGraphDiv = require('../assets/create_graph_div'); var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; var gd = createGraphDiv(); @@ -154,7 +154,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('scatter', tests); + downloadCSV('scatter', tests); } }); }); diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index 55c0aa6bf5c..303aaa4f138 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -2,7 +2,7 @@ var createGraphDiv = require('../assets/create_graph_div'); var delay = require('../assets/delay'); var Plotly = require('../../../lib/core'); var PlotlyScattergl = require('../../../lib/scattergl'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyScattergl); @@ -153,7 +153,7 @@ tests.forEach(function(spec, index) { tests[index].raw[t] = delta; if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('scattergl', tests); + downloadCSV('scattergl', tests); } }); }); diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index 9c53a1deca1..75a779d38d4 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -3,7 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/core'); var PlotlyViolin = require('../../../lib/violin'); -var writeRawDataAsCSV = require('./assets/post_process').writeRawDataAsCSV; +var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; Plotly.register(PlotlyViolin); @@ -157,7 +157,7 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); if(t === nTimes && index === tests.length - 1) { - writeRawDataAsCSV('violin', tests); + downloadCSV('violin', tests); } }); }); From cd5da3255f1a336576818f19df44cfeaf61b5ac3 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:14:15 -0400 Subject: [PATCH 23/45] add markers+lines cases --- .../jasmine/performance_tests/scatter_test.js | 42 +++++++++++++++++++ .../performance_tests/scattergl_test.js | 42 +++++++++++++++++++ 2 files changed, 84 insertions(+) diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index c08425a87ee..001f8125b16 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -38,6 +38,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 1 }, { n: 64000, mode: 'lines', nTraces: 1 +}, { + n: 1000, mode: 'markers+lines', nTraces: 1 +}, { + n: 2000, mode: 'markers+lines', nTraces: 1 +}, { + n: 4000, mode: 'markers+lines', nTraces: 1 +}, { + n: 8000, mode: 'markers+lines', nTraces: 1 +}, { + n: 16000, mode: 'markers+lines', nTraces: 1 +}, { + n: 32000, mode: 'markers+lines', nTraces: 1 +}, { + n: 64000, mode: 'markers+lines', nTraces: 1 }, { n: 1000, mode: 'markers', nTraces: 10 }, { @@ -66,6 +80,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 10 }, { n: 64000, mode: 'lines', nTraces: 10 +}, { + n: 1000, mode: 'markers+lines', nTraces: 10 +}, { + n: 2000, mode: 'markers+lines', nTraces: 10 +}, { + n: 4000, mode: 'markers+lines', nTraces: 10 +}, { + n: 8000, mode: 'markers+lines', nTraces: 10 +}, { + n: 16000, mode: 'markers+lines', nTraces: 10 +}, { + n: 32000, mode: 'markers+lines', nTraces: 10 +}, { + n: 64000, mode: 'markers+lines', nTraces: 10 }, { n: 1000, mode: 'markers', nTraces: 100 }, { @@ -94,6 +122,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 100 }, { n: 64000, mode: 'lines', nTraces: 100 +}, { + n: 1000, mode: 'markers+lines', nTraces: 100 +}, { + n: 2000, mode: 'markers+lines', nTraces: 100 +}, { + n: 4000, mode: 'markers+lines', nTraces: 100 +}, { + n: 8000, mode: 'markers+lines', nTraces: 100 +}, { + n: 16000, mode: 'markers+lines', nTraces: 100 +}, { + n: 32000, mode: 'markers+lines', nTraces: 100 +}, { + n: 64000, mode: 'markers+lines', nTraces: 100 }]; tests.forEach(function(spec, index) { diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index 303aaa4f138..f415efd58c2 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -40,6 +40,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 1 }, { n: 64000, mode: 'lines', nTraces: 1 +}, { + n: 1000, mode: 'markers+lines', nTraces: 1 +}, { + n: 2000, mode: 'markers+lines', nTraces: 1 +}, { + n: 4000, mode: 'markers+lines', nTraces: 1 +}, { + n: 8000, mode: 'markers+lines', nTraces: 1 +}, { + n: 16000, mode: 'markers+lines', nTraces: 1 +}, { + n: 32000, mode: 'markers+lines', nTraces: 1 +}, { + n: 64000, mode: 'markers+lines', nTraces: 1 }, { n: 1000, mode: 'markers', nTraces: 10 }, { @@ -68,6 +82,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 10 }, { n: 64000, mode: 'lines', nTraces: 10 +}, { + n: 1000, mode: 'markers+lines', nTraces: 10 +}, { + n: 2000, mode: 'markers+lines', nTraces: 10 +}, { + n: 4000, mode: 'markers+lines', nTraces: 10 +}, { + n: 8000, mode: 'markers+lines', nTraces: 10 +}, { + n: 16000, mode: 'markers+lines', nTraces: 10 +}, { + n: 32000, mode: 'markers+lines', nTraces: 10 +}, { + n: 64000, mode: 'markers+lines', nTraces: 10 }, { n: 1000, mode: 'markers', nTraces: 100 }, { @@ -96,6 +124,20 @@ var tests = [{ n: 32000, mode: 'lines', nTraces: 100 }, { n: 64000, mode: 'lines', nTraces: 100 +}, { + n: 1000, mode: 'markers+lines', nTraces: 100 +}, { + n: 2000, mode: 'markers+lines', nTraces: 100 +}, { + n: 4000, mode: 'markers+lines', nTraces: 100 +}, { + n: 8000, mode: 'markers+lines', nTraces: 100 +}, { + n: 16000, mode: 'markers+lines', nTraces: 100 +}, { + n: 32000, mode: 'markers+lines', nTraces: 100 +}, { + n: 64000, mode: 'markers+lines', nTraces: 100 }]; tests.forEach(function(spec, index) { From a4aa4367a6b062d826b68637e74b209d797fe639 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:16:59 -0400 Subject: [PATCH 24/45] use normal arrays in tests --- test/jasmine/performance_tests/contour_test.js | 6 +++--- test/jasmine/performance_tests/heatmap_test.js | 6 +++--- test/jasmine/performance_tests/image_test.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index c38e1722b02..52f69df411c 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -37,11 +37,11 @@ tests.forEach(function(spec, index) { var B = spec.ny; spec.n = A * B; - var x = Uint16Array.from({ length: A }, (_, i) => i); - var y = Uint16Array.from({ length: B }, (_, i) => i); + var x = Array.from({ length: A }, (_, i) => i); + var y = Array.from({ length: B }, (_, i) => i); var z = []; for(var k = 0; k < B ; k++) { - z[k] = Float64Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); + z[k] = Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); } var mock = { diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index 0c0ae151e77..a948bf8fb73 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -37,11 +37,11 @@ tests.forEach(function(spec, index) { var B = spec.ny; spec.n = A * B; - var x = Uint16Array.from({ length: A }, (_, i) => i); - var y = Uint16Array.from({ length: B }, (_, i) => i); + var x = Array.from({ length: A }, (_, i) => i); + var y = Array.from({ length: B }, (_, i) => i); var z = []; for(var k = 0; k < B ; k++) { - z[k] = Float64Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); + z[k] = Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); } var mock = { diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 39ddf256477..4dfaf7beb0a 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -40,8 +40,8 @@ tests.forEach(function(spec, index) { var B = spec.ny; spec.n = A * B; - var x = Uint16Array.from({ length: A }, (_, i) => i); - var y = Uint16Array.from({ length: B }, (_, i) => i); + var x = Array.from({ length: A }, (_, i) => i); + var y = Array.from({ length: B }, (_, i) => i); var z = []; for(var k = 0; k < B ; k++) { z[k] = []; From 98252d41ac104c21eb0ec63ad946d286ce6d312f Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:31:18 -0400 Subject: [PATCH 25/45] add scattergeo tests --- .../performance_tests/scattergeo_test.js | 204 ++++++++++++++++++ 1 file changed, 204 insertions(+) create mode 100644 test/jasmine/performance_tests/scattergeo_test.js diff --git a/test/jasmine/performance_tests/scattergeo_test.js b/test/jasmine/performance_tests/scattergeo_test.js new file mode 100644 index 00000000000..d0db3c5cedc --- /dev/null +++ b/test/jasmine/performance_tests/scattergeo_test.js @@ -0,0 +1,204 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var Plotly = require('../../../lib/core'); +var PlotlyScattergeo = require('../../../lib/scattergeo'); +var downloadCSV = require('./assets/post_process').downloadCSV; +var nSamples = require('./assets/constants').nSamples; + +Plotly.register(PlotlyScattergeo); + +var gd = createGraphDiv(); + +const samples = Array.from({ length: nSamples }, (_, i) => i); +const nTimes = samples.length - 1; + +var tests = [{ + n: 1000, mode: 'markers', nTraces: 1 +}, { + n: 2000, mode: 'markers', nTraces: 1 +}, { + n: 4000, mode: 'markers', nTraces: 1 +}, { + n: 8000, mode: 'markers', nTraces: 1 +}, { + n: 16000, mode: 'markers', nTraces: 1 +}, { + n: 32000, mode: 'markers', nTraces: 1 +}, { + n: 64000, mode: 'markers', nTraces: 1 +}, { + n: 1000, mode: 'lines', nTraces: 1 +}, { + n: 2000, mode: 'lines', nTraces: 1 +}, { + n: 4000, mode: 'lines', nTraces: 1 +}, { + n: 8000, mode: 'lines', nTraces: 1 +}, { + n: 16000, mode: 'lines', nTraces: 1 +}, { + n: 32000, mode: 'lines', nTraces: 1 +}, { + n: 64000, mode: 'lines', nTraces: 1 +}, { + n: 1000, mode: 'markers+lines', nTraces: 1 +}, { + n: 2000, mode: 'markers+lines', nTraces: 1 +}, { + n: 4000, mode: 'markers+lines', nTraces: 1 +}, { + n: 8000, mode: 'markers+lines', nTraces: 1 +}, { + n: 16000, mode: 'markers+lines', nTraces: 1 +}, { + n: 32000, mode: 'markers+lines', nTraces: 1 +}, { + n: 64000, mode: 'markers+lines', nTraces: 1 +}, { + n: 1000, mode: 'markers', nTraces: 10 +}, { + n: 2000, mode: 'markers', nTraces: 10 +}, { + n: 4000, mode: 'markers', nTraces: 10 +}, { + n: 8000, mode: 'markers', nTraces: 10 +}, { + n: 16000, mode: 'markers', nTraces: 10 +}, { + n: 32000, mode: 'markers', nTraces: 10 +}, { + n: 64000, mode: 'markers', nTraces: 10 +}, { + n: 1000, mode: 'lines', nTraces: 10 +}, { + n: 2000, mode: 'lines', nTraces: 10 +}, { + n: 4000, mode: 'lines', nTraces: 10 +}, { + n: 8000, mode: 'lines', nTraces: 10 +}, { + n: 16000, mode: 'lines', nTraces: 10 +}, { + n: 32000, mode: 'lines', nTraces: 10 +}, { + n: 64000, mode: 'lines', nTraces: 10 +}, { + n: 1000, mode: 'markers+lines', nTraces: 10 +}, { + n: 2000, mode: 'markers+lines', nTraces: 10 +}, { + n: 4000, mode: 'markers+lines', nTraces: 10 +}, { + n: 8000, mode: 'markers+lines', nTraces: 10 +}, { + n: 16000, mode: 'markers+lines', nTraces: 10 +}, { + n: 32000, mode: 'markers+lines', nTraces: 10 +}, { + n: 64000, mode: 'markers+lines', nTraces: 10 +}, { + n: 1000, mode: 'markers', nTraces: 100 +}, { + n: 2000, mode: 'markers', nTraces: 100 +}, { + n: 4000, mode: 'markers', nTraces: 100 +}, { + n: 8000, mode: 'markers', nTraces: 100 +}, { + n: 16000, mode: 'markers', nTraces: 100 +}, { + n: 32000, mode: 'markers', nTraces: 100 +}, { + n: 64000, mode: 'markers', nTraces: 100 +}, { + n: 1000, mode: 'lines', nTraces: 100 +}, { + n: 2000, mode: 'lines', nTraces: 100 +}, { + n: 4000, mode: 'lines', nTraces: 100 +}, { + n: 8000, mode: 'lines', nTraces: 100 +}, { + n: 16000, mode: 'lines', nTraces: 100 +}, { + n: 32000, mode: 'lines', nTraces: 100 +}, { + n: 64000, mode: 'lines', nTraces: 100 +}, { + n: 1000, mode: 'markers+lines', nTraces: 100 +}, { + n: 2000, mode: 'markers+lines', nTraces: 100 +}, { + n: 4000, mode: 'markers+lines', nTraces: 100 +}, { + n: 8000, mode: 'markers+lines', nTraces: 100 +}, { + n: 16000, mode: 'markers+lines', nTraces: 100 +}, { + n: 32000, mode: 'markers+lines', nTraces: 100 +}, { + n: 64000, mode: 'markers+lines', nTraces: 100 +}]; + +tests.forEach(function(spec, index) { + describe('Performance test ' + spec.nTraces + 'scattergeo | size:' + spec.n + ' | mode: ' + spec.mode, function() { + 'use strict'; + + var startTime, endTime; + + beforeEach(function(done) { + var y = Array.from({ length: spec.n }, (_, i) => 0.001 * i * Math.cos(Math.sqrt(i))); + + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'scattergeo', + mode: spec.mode, + lat: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + lon: Array.from({ length: nPerTrace }, (_, i) => -180 + 0.005 * (i + k * nPerTrace)) + }); + } + + var mock = { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; + + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); + + Plotly.newPlot(gd, mock); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + samples.forEach(function(t) { + it('should graph scattergeo traces | turn: ' + t, function() { + var delta = endTime - startTime; + + if(t === 0) { + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(t === nTimes && index === tests.length - 1) { + downloadCSV('scattergeo', tests); + } + }); + }); + }); +}); From 3134b6168de626f4115f13deeaf0ec04beb90a57 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:33:19 -0400 Subject: [PATCH 26/45] set nSamples to 4 --- test/jasmine/performance_tests/assets/constants.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jasmine/performance_tests/assets/constants.js b/test/jasmine/performance_tests/assets/constants.js index 53fb3438b71..0fe113801ce 100644 --- a/test/jasmine/performance_tests/assets/constants.js +++ b/test/jasmine/performance_tests/assets/constants.js @@ -1,5 +1,5 @@ 'use strict'; module.exports = { - nSamples: 1 + nSamples: 4 }; From d4f3af2eb36f76c816529eabb02f2dafc103c288 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 14:57:05 -0400 Subject: [PATCH 27/45] format test messages --- test/jasmine/performance_tests/bar_test.js | 2 +- test/jasmine/performance_tests/box_test.js | 2 +- test/jasmine/performance_tests/histogram_test.js | 2 +- test/jasmine/performance_tests/scatter_test.js | 2 +- test/jasmine/performance_tests/scattergeo_test.js | 2 +- test/jasmine/performance_tests/scattergl_test.js | 2 +- test/jasmine/performance_tests/violin_test.js | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index 9edca9ec1b9..c66591a0cde 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -100,7 +100,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'bar | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' bar | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index e5a7bae6678..37579a579be 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -100,7 +100,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'box | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' box | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index ccf3e75782f..ecb114119fd 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -100,7 +100,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'histogram | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' histogram | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 001f8125b16..382abeec502 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -139,7 +139,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'scatter | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' scatter | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/scattergeo_test.js b/test/jasmine/performance_tests/scattergeo_test.js index d0db3c5cedc..24314337809 100644 --- a/test/jasmine/performance_tests/scattergeo_test.js +++ b/test/jasmine/performance_tests/scattergeo_test.js @@ -141,7 +141,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'scattergeo | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' scattergeo | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index f415efd58c2..1a38f4870c9 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -141,7 +141,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'scattergl | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' scattergl | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index 75a779d38d4..06c0f6c62c2 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -100,7 +100,7 @@ var tests = [{ }]; tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + 'violin | size:' + spec.n + ' | mode: ' + spec.mode, function() { + describe('Performance test ' + spec.nTraces + ' violin | size:' + spec.n + ' | mode: ' + spec.mode, function() { 'use strict'; var startTime, endTime; From 5d30519eac891e2466076fcf20f209c142ffbaf2 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 16:16:54 -0400 Subject: [PATCH 28/45] revisit test descriptions --- test/jasmine/performance_tests/bar_test.js | 97 ++---------- test/jasmine/performance_tests/box_test.js | 97 ++---------- .../jasmine/performance_tests/contour_test.js | 26 ++-- .../jasmine/performance_tests/heatmap_test.js | 26 ++-- .../performance_tests/histogram_test.js | 97 ++---------- test/jasmine/performance_tests/image_test.js | 29 ++-- .../jasmine/performance_tests/scatter_test.js | 139 ++---------------- .../performance_tests/scattergeo_test.js | 139 ++---------------- .../performance_tests/scattergl_test.js | 139 ++---------------- test/jasmine/performance_tests/violin_test.js | 97 ++---------- 10 files changed, 114 insertions(+), 772 deletions(-) diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js index c66591a0cde..9bb3cbe911e 100644 --- a/test/jasmine/performance_tests/bar_test.js +++ b/test/jasmine/performance_tests/bar_test.js @@ -13,91 +13,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'group', nTraces: 1 -}, { - n: 2000, mode: 'group', nTraces: 1 -}, { - n: 4000, mode: 'group', nTraces: 1 -}, { - n: 8000, mode: 'group', nTraces: 1 -}, { - n: 16000, mode: 'group', nTraces: 1 -}, { - n: 32000, mode: 'group', nTraces: 1 -}, { - n: 64000, mode: 'group', nTraces: 1 -}, { - n: 1000, mode: 'stack', nTraces: 1 -}, { - n: 2000, mode: 'stack', nTraces: 1 -}, { - n: 4000, mode: 'stack', nTraces: 1 -}, { - n: 8000, mode: 'stack', nTraces: 1 -}, { - n: 16000, mode: 'stack', nTraces: 1 -}, { - n: 32000, mode: 'stack', nTraces: 1 -}, { - n: 64000, mode: 'stack', nTraces: 1 -}, { - n: 1000, mode: 'group', nTraces: 10 -}, { - n: 2000, mode: 'group', nTraces: 10 -}, { - n: 4000, mode: 'group', nTraces: 10 -}, { - n: 8000, mode: 'group', nTraces: 10 -}, { - n: 16000, mode: 'group', nTraces: 10 -}, { - n: 32000, mode: 'group', nTraces: 10 -}, { - n: 64000, mode: 'group', nTraces: 10 -}, { - n: 1000, mode: 'stack', nTraces: 10 -}, { - n: 2000, mode: 'stack', nTraces: 10 -}, { - n: 4000, mode: 'stack', nTraces: 10 -}, { - n: 8000, mode: 'stack', nTraces: 10 -}, { - n: 16000, mode: 'stack', nTraces: 10 -}, { - n: 32000, mode: 'stack', nTraces: 10 -}, { - n: 64000, mode: 'stack', nTraces: 10 -}, { - n: 1000, mode: 'group', nTraces: 100 -}, { - n: 2000, mode: 'group', nTraces: 100 -}, { - n: 4000, mode: 'group', nTraces: 100 -}, { - n: 8000, mode: 'group', nTraces: 100 -}, { - n: 16000, mode: 'group', nTraces: 100 -}, { - n: 32000, mode: 'group', nTraces: 100 -}, { - n: 64000, mode: 'group', nTraces: 100 -}, { - n: 1000, mode: 'stack', nTraces: 100 -}, { - n: 2000, mode: 'stack', nTraces: 100 -}, { - n: 4000, mode: 'stack', nTraces: 100 -}, { - n: 8000, mode: 'stack', nTraces: 100 -}, { - n: 16000, mode: 'stack', nTraces: 100 -}, { - n: 32000, mode: 'stack', nTraces: 100 -}, { - n: 64000, mode: 'stack', nTraces: 100 -}]; +var tests = []; +for(let mode of ['group', 'stack']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' bar | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js index 37579a579be..f9361df1524 100644 --- a/test/jasmine/performance_tests/box_test.js +++ b/test/jasmine/performance_tests/box_test.js @@ -13,91 +13,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'no points', nTraces: 1 -}, { - n: 2000, mode: 'no points', nTraces: 1 -}, { - n: 4000, mode: 'no points', nTraces: 1 -}, { - n: 8000, mode: 'no points', nTraces: 1 -}, { - n: 16000, mode: 'no points', nTraces: 1 -}, { - n: 32000, mode: 'no points', nTraces: 1 -}, { - n: 64000, mode: 'no points', nTraces: 1 -}, { - n: 1000, mode: 'all points', nTraces: 1 -}, { - n: 2000, mode: 'all points', nTraces: 1 -}, { - n: 4000, mode: 'all points', nTraces: 1 -}, { - n: 8000, mode: 'all points', nTraces: 1 -}, { - n: 16000, mode: 'all points', nTraces: 1 -}, { - n: 32000, mode: 'all points', nTraces: 1 -}, { - n: 64000, mode: 'all points', nTraces: 1 -}, { - n: 1000, mode: 'no points', nTraces: 10 -}, { - n: 2000, mode: 'no points', nTraces: 10 -}, { - n: 4000, mode: 'no points', nTraces: 10 -}, { - n: 8000, mode: 'no points', nTraces: 10 -}, { - n: 16000, mode: 'no points', nTraces: 10 -}, { - n: 32000, mode: 'no points', nTraces: 10 -}, { - n: 64000, mode: 'no points', nTraces: 10 -}, { - n: 1000, mode: 'all points', nTraces: 10 -}, { - n: 2000, mode: 'all points', nTraces: 10 -}, { - n: 4000, mode: 'all points', nTraces: 10 -}, { - n: 8000, mode: 'all points', nTraces: 10 -}, { - n: 16000, mode: 'all points', nTraces: 10 -}, { - n: 32000, mode: 'all points', nTraces: 10 -}, { - n: 64000, mode: 'all points', nTraces: 10 -}, { - n: 1000, mode: 'no points', nTraces: 100 -}, { - n: 2000, mode: 'no points', nTraces: 100 -}, { - n: 4000, mode: 'no points', nTraces: 100 -}, { - n: 8000, mode: 'no points', nTraces: 100 -}, { - n: 16000, mode: 'no points', nTraces: 100 -}, { - n: 32000, mode: 'no points', nTraces: 100 -}, { - n: 64000, mode: 'no points', nTraces: 100 -}, { - n: 1000, mode: 'all points', nTraces: 100 -}, { - n: 2000, mode: 'all points', nTraces: 100 -}, { - n: 4000, mode: 'all points', nTraces: 100 -}, { - n: 8000, mode: 'all points', nTraces: 100 -}, { - n: 16000, mode: 'all points', nTraces: 100 -}, { - n: 32000, mode: 'all points', nTraces: 100 -}, { - n: 64000, mode: 'all points', nTraces: 100 -}]; +var tests = []; +for(let mode of ['no points', 'all points']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' box | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js index 52f69df411c..2111fd9bd44 100644 --- a/test/jasmine/performance_tests/contour_test.js +++ b/test/jasmine/performance_tests/contour_test.js @@ -13,21 +13,16 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - nx: 50, ny: 20 -}, { - nx: 100, ny: 40 -}, { - nx: 200, ny: 80 -}, { - nx: 400, ny: 160 -}, { - nx: 800, ny: 320 -}, { - nx: 1600, ny: 640 -}, { - nx: 3200, ny: 1280 -}]; +var tests = []; +for(let m of [10, 20, 40, 80, 160, 320, 640]) { + let nx = 5 * m; + let ny = 2 * m; + tests.push({ + nx: nx, + ny: ny, + n: nx * ny, + }); +} tests.forEach(function(spec, index) { describe('Performance test contour | size:' + spec.nx + 'X' + spec.ny, function() { @@ -35,7 +30,6 @@ tests.forEach(function(spec, index) { var A = spec.nx; var B = spec.ny; - spec.n = A * B; var x = Array.from({ length: A }, (_, i) => i); var y = Array.from({ length: B }, (_, i) => i); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js index a948bf8fb73..93d8ac8c16a 100644 --- a/test/jasmine/performance_tests/heatmap_test.js +++ b/test/jasmine/performance_tests/heatmap_test.js @@ -13,21 +13,16 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - nx: 50, ny: 20 -}, { - nx: 100, ny: 40 -}, { - nx: 200, ny: 80 -}, { - nx: 400, ny: 160 -}, { - nx: 800, ny: 320 -}, { - nx: 1600, ny: 640 -}, { - nx: 3200, ny: 1280 -}]; +var tests = []; +for(let m of [10, 20, 40, 80, 160, 320, 640]) { + let nx = 5 * m; + let ny = 2 * m; + tests.push({ + nx: nx, + ny: ny, + n: nx * ny, + }); +} tests.forEach(function(spec, index) { describe('Performance test heatmap | size:' + spec.nx + 'X' + spec.ny, function() { @@ -35,7 +30,6 @@ tests.forEach(function(spec, index) { var A = spec.nx; var B = spec.ny; - spec.n = A * B; var x = Array.from({ length: A }, (_, i) => i); var y = Array.from({ length: B }, (_, i) => i); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js index ecb114119fd..66a03e613f7 100644 --- a/test/jasmine/performance_tests/histogram_test.js +++ b/test/jasmine/performance_tests/histogram_test.js @@ -13,91 +13,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'group', nTraces: 1 -}, { - n: 2000, mode: 'group', nTraces: 1 -}, { - n: 4000, mode: 'group', nTraces: 1 -}, { - n: 8000, mode: 'group', nTraces: 1 -}, { - n: 16000, mode: 'group', nTraces: 1 -}, { - n: 32000, mode: 'group', nTraces: 1 -}, { - n: 64000, mode: 'group', nTraces: 1 -}, { - n: 1000, mode: 'stack', nTraces: 1 -}, { - n: 2000, mode: 'stack', nTraces: 1 -}, { - n: 4000, mode: 'stack', nTraces: 1 -}, { - n: 8000, mode: 'stack', nTraces: 1 -}, { - n: 16000, mode: 'stack', nTraces: 1 -}, { - n: 32000, mode: 'stack', nTraces: 1 -}, { - n: 64000, mode: 'stack', nTraces: 1 -}, { - n: 1000, mode: 'group', nTraces: 10 -}, { - n: 2000, mode: 'group', nTraces: 10 -}, { - n: 4000, mode: 'group', nTraces: 10 -}, { - n: 8000, mode: 'group', nTraces: 10 -}, { - n: 16000, mode: 'group', nTraces: 10 -}, { - n: 32000, mode: 'group', nTraces: 10 -}, { - n: 64000, mode: 'group', nTraces: 10 -}, { - n: 1000, mode: 'stack', nTraces: 10 -}, { - n: 2000, mode: 'stack', nTraces: 10 -}, { - n: 4000, mode: 'stack', nTraces: 10 -}, { - n: 8000, mode: 'stack', nTraces: 10 -}, { - n: 16000, mode: 'stack', nTraces: 10 -}, { - n: 32000, mode: 'stack', nTraces: 10 -}, { - n: 64000, mode: 'stack', nTraces: 10 -}, { - n: 1000, mode: 'group', nTraces: 100 -}, { - n: 2000, mode: 'group', nTraces: 100 -}, { - n: 4000, mode: 'group', nTraces: 100 -}, { - n: 8000, mode: 'group', nTraces: 100 -}, { - n: 16000, mode: 'group', nTraces: 100 -}, { - n: 32000, mode: 'group', nTraces: 100 -}, { - n: 64000, mode: 'group', nTraces: 100 -}, { - n: 1000, mode: 'stack', nTraces: 100 -}, { - n: 2000, mode: 'stack', nTraces: 100 -}, { - n: 4000, mode: 'stack', nTraces: 100 -}, { - n: 8000, mode: 'stack', nTraces: 100 -}, { - n: 16000, mode: 'stack', nTraces: 100 -}, { - n: 32000, mode: 'stack', nTraces: 100 -}, { - n: 64000, mode: 'stack', nTraces: 100 -}]; +var tests = []; +for(let mode of ['group', 'stack']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' histogram | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js index 4dfaf7beb0a..3e87eec172e 100644 --- a/test/jasmine/performance_tests/image_test.js +++ b/test/jasmine/performance_tests/image_test.js @@ -13,32 +13,23 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - nx: 50, ny: 20 -}, { - nx: 100, ny: 40 -}, { - nx: 200, ny: 80 -}, { - nx: 400, ny: 160 -}, { - nx: 800, ny: 320 -}, { - nx: 1600, ny: 640 -}, { - nx: 3200, ny: 1280 -}]; +var tests = []; +for(let m of [10, 20, 40, 80, 160, 320, 640]) { + let nx = 5 * m; + let ny = 2 * m; + tests.push({ + nx: nx, + ny: ny, + n: nx * ny, + }); +} tests.forEach(function(spec, index) { describe('Performance test image | size:' + spec.nx + 'X' + spec.ny, function() { 'use strict'; - const samples = Array.from({ length: nSamples }, (_, i) => i); - const nTimes = samples.length - 1; - var A = spec.nx; var B = spec.ny; - spec.n = A * B; var x = Array.from({ length: A }, (_, i) => i); var y = Array.from({ length: B }, (_, i) => i); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js index 382abeec502..97b21112856 100644 --- a/test/jasmine/performance_tests/scatter_test.js +++ b/test/jasmine/performance_tests/scatter_test.js @@ -10,133 +10,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'markers', nTraces: 1 -}, { - n: 2000, mode: 'markers', nTraces: 1 -}, { - n: 4000, mode: 'markers', nTraces: 1 -}, { - n: 8000, mode: 'markers', nTraces: 1 -}, { - n: 16000, mode: 'markers', nTraces: 1 -}, { - n: 32000, mode: 'markers', nTraces: 1 -}, { - n: 64000, mode: 'markers', nTraces: 1 -}, { - n: 1000, mode: 'lines', nTraces: 1 -}, { - n: 2000, mode: 'lines', nTraces: 1 -}, { - n: 4000, mode: 'lines', nTraces: 1 -}, { - n: 8000, mode: 'lines', nTraces: 1 -}, { - n: 16000, mode: 'lines', nTraces: 1 -}, { - n: 32000, mode: 'lines', nTraces: 1 -}, { - n: 64000, mode: 'lines', nTraces: 1 -}, { - n: 1000, mode: 'markers+lines', nTraces: 1 -}, { - n: 2000, mode: 'markers+lines', nTraces: 1 -}, { - n: 4000, mode: 'markers+lines', nTraces: 1 -}, { - n: 8000, mode: 'markers+lines', nTraces: 1 -}, { - n: 16000, mode: 'markers+lines', nTraces: 1 -}, { - n: 32000, mode: 'markers+lines', nTraces: 1 -}, { - n: 64000, mode: 'markers+lines', nTraces: 1 -}, { - n: 1000, mode: 'markers', nTraces: 10 -}, { - n: 2000, mode: 'markers', nTraces: 10 -}, { - n: 4000, mode: 'markers', nTraces: 10 -}, { - n: 8000, mode: 'markers', nTraces: 10 -}, { - n: 16000, mode: 'markers', nTraces: 10 -}, { - n: 32000, mode: 'markers', nTraces: 10 -}, { - n: 64000, mode: 'markers', nTraces: 10 -}, { - n: 1000, mode: 'lines', nTraces: 10 -}, { - n: 2000, mode: 'lines', nTraces: 10 -}, { - n: 4000, mode: 'lines', nTraces: 10 -}, { - n: 8000, mode: 'lines', nTraces: 10 -}, { - n: 16000, mode: 'lines', nTraces: 10 -}, { - n: 32000, mode: 'lines', nTraces: 10 -}, { - n: 64000, mode: 'lines', nTraces: 10 -}, { - n: 1000, mode: 'markers+lines', nTraces: 10 -}, { - n: 2000, mode: 'markers+lines', nTraces: 10 -}, { - n: 4000, mode: 'markers+lines', nTraces: 10 -}, { - n: 8000, mode: 'markers+lines', nTraces: 10 -}, { - n: 16000, mode: 'markers+lines', nTraces: 10 -}, { - n: 32000, mode: 'markers+lines', nTraces: 10 -}, { - n: 64000, mode: 'markers+lines', nTraces: 10 -}, { - n: 1000, mode: 'markers', nTraces: 100 -}, { - n: 2000, mode: 'markers', nTraces: 100 -}, { - n: 4000, mode: 'markers', nTraces: 100 -}, { - n: 8000, mode: 'markers', nTraces: 100 -}, { - n: 16000, mode: 'markers', nTraces: 100 -}, { - n: 32000, mode: 'markers', nTraces: 100 -}, { - n: 64000, mode: 'markers', nTraces: 100 -}, { - n: 1000, mode: 'lines', nTraces: 100 -}, { - n: 2000, mode: 'lines', nTraces: 100 -}, { - n: 4000, mode: 'lines', nTraces: 100 -}, { - n: 8000, mode: 'lines', nTraces: 100 -}, { - n: 16000, mode: 'lines', nTraces: 100 -}, { - n: 32000, mode: 'lines', nTraces: 100 -}, { - n: 64000, mode: 'lines', nTraces: 100 -}, { - n: 1000, mode: 'markers+lines', nTraces: 100 -}, { - n: 2000, mode: 'markers+lines', nTraces: 100 -}, { - n: 4000, mode: 'markers+lines', nTraces: 100 -}, { - n: 8000, mode: 'markers+lines', nTraces: 100 -}, { - n: 16000, mode: 'markers+lines', nTraces: 100 -}, { - n: 32000, mode: 'markers+lines', nTraces: 100 -}, { - n: 64000, mode: 'markers+lines', nTraces: 100 -}]; +var tests = []; +for(let mode of ['markers', 'lines', 'markers+lines']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' scatter | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/scattergeo_test.js b/test/jasmine/performance_tests/scattergeo_test.js index 24314337809..8c456201408 100644 --- a/test/jasmine/performance_tests/scattergeo_test.js +++ b/test/jasmine/performance_tests/scattergeo_test.js @@ -12,133 +12,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'markers', nTraces: 1 -}, { - n: 2000, mode: 'markers', nTraces: 1 -}, { - n: 4000, mode: 'markers', nTraces: 1 -}, { - n: 8000, mode: 'markers', nTraces: 1 -}, { - n: 16000, mode: 'markers', nTraces: 1 -}, { - n: 32000, mode: 'markers', nTraces: 1 -}, { - n: 64000, mode: 'markers', nTraces: 1 -}, { - n: 1000, mode: 'lines', nTraces: 1 -}, { - n: 2000, mode: 'lines', nTraces: 1 -}, { - n: 4000, mode: 'lines', nTraces: 1 -}, { - n: 8000, mode: 'lines', nTraces: 1 -}, { - n: 16000, mode: 'lines', nTraces: 1 -}, { - n: 32000, mode: 'lines', nTraces: 1 -}, { - n: 64000, mode: 'lines', nTraces: 1 -}, { - n: 1000, mode: 'markers+lines', nTraces: 1 -}, { - n: 2000, mode: 'markers+lines', nTraces: 1 -}, { - n: 4000, mode: 'markers+lines', nTraces: 1 -}, { - n: 8000, mode: 'markers+lines', nTraces: 1 -}, { - n: 16000, mode: 'markers+lines', nTraces: 1 -}, { - n: 32000, mode: 'markers+lines', nTraces: 1 -}, { - n: 64000, mode: 'markers+lines', nTraces: 1 -}, { - n: 1000, mode: 'markers', nTraces: 10 -}, { - n: 2000, mode: 'markers', nTraces: 10 -}, { - n: 4000, mode: 'markers', nTraces: 10 -}, { - n: 8000, mode: 'markers', nTraces: 10 -}, { - n: 16000, mode: 'markers', nTraces: 10 -}, { - n: 32000, mode: 'markers', nTraces: 10 -}, { - n: 64000, mode: 'markers', nTraces: 10 -}, { - n: 1000, mode: 'lines', nTraces: 10 -}, { - n: 2000, mode: 'lines', nTraces: 10 -}, { - n: 4000, mode: 'lines', nTraces: 10 -}, { - n: 8000, mode: 'lines', nTraces: 10 -}, { - n: 16000, mode: 'lines', nTraces: 10 -}, { - n: 32000, mode: 'lines', nTraces: 10 -}, { - n: 64000, mode: 'lines', nTraces: 10 -}, { - n: 1000, mode: 'markers+lines', nTraces: 10 -}, { - n: 2000, mode: 'markers+lines', nTraces: 10 -}, { - n: 4000, mode: 'markers+lines', nTraces: 10 -}, { - n: 8000, mode: 'markers+lines', nTraces: 10 -}, { - n: 16000, mode: 'markers+lines', nTraces: 10 -}, { - n: 32000, mode: 'markers+lines', nTraces: 10 -}, { - n: 64000, mode: 'markers+lines', nTraces: 10 -}, { - n: 1000, mode: 'markers', nTraces: 100 -}, { - n: 2000, mode: 'markers', nTraces: 100 -}, { - n: 4000, mode: 'markers', nTraces: 100 -}, { - n: 8000, mode: 'markers', nTraces: 100 -}, { - n: 16000, mode: 'markers', nTraces: 100 -}, { - n: 32000, mode: 'markers', nTraces: 100 -}, { - n: 64000, mode: 'markers', nTraces: 100 -}, { - n: 1000, mode: 'lines', nTraces: 100 -}, { - n: 2000, mode: 'lines', nTraces: 100 -}, { - n: 4000, mode: 'lines', nTraces: 100 -}, { - n: 8000, mode: 'lines', nTraces: 100 -}, { - n: 16000, mode: 'lines', nTraces: 100 -}, { - n: 32000, mode: 'lines', nTraces: 100 -}, { - n: 64000, mode: 'lines', nTraces: 100 -}, { - n: 1000, mode: 'markers+lines', nTraces: 100 -}, { - n: 2000, mode: 'markers+lines', nTraces: 100 -}, { - n: 4000, mode: 'markers+lines', nTraces: 100 -}, { - n: 8000, mode: 'markers+lines', nTraces: 100 -}, { - n: 16000, mode: 'markers+lines', nTraces: 100 -}, { - n: 32000, mode: 'markers+lines', nTraces: 100 -}, { - n: 64000, mode: 'markers+lines', nTraces: 100 -}]; +var tests = []; +for(let mode of ['markers', 'lines', 'markers+lines']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' scattergeo | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js index 1a38f4870c9..05261f4e981 100644 --- a/test/jasmine/performance_tests/scattergl_test.js +++ b/test/jasmine/performance_tests/scattergl_test.js @@ -12,133 +12,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'markers', nTraces: 1 -}, { - n: 2000, mode: 'markers', nTraces: 1 -}, { - n: 4000, mode: 'markers', nTraces: 1 -}, { - n: 8000, mode: 'markers', nTraces: 1 -}, { - n: 16000, mode: 'markers', nTraces: 1 -}, { - n: 32000, mode: 'markers', nTraces: 1 -}, { - n: 64000, mode: 'markers', nTraces: 1 -}, { - n: 1000, mode: 'lines', nTraces: 1 -}, { - n: 2000, mode: 'lines', nTraces: 1 -}, { - n: 4000, mode: 'lines', nTraces: 1 -}, { - n: 8000, mode: 'lines', nTraces: 1 -}, { - n: 16000, mode: 'lines', nTraces: 1 -}, { - n: 32000, mode: 'lines', nTraces: 1 -}, { - n: 64000, mode: 'lines', nTraces: 1 -}, { - n: 1000, mode: 'markers+lines', nTraces: 1 -}, { - n: 2000, mode: 'markers+lines', nTraces: 1 -}, { - n: 4000, mode: 'markers+lines', nTraces: 1 -}, { - n: 8000, mode: 'markers+lines', nTraces: 1 -}, { - n: 16000, mode: 'markers+lines', nTraces: 1 -}, { - n: 32000, mode: 'markers+lines', nTraces: 1 -}, { - n: 64000, mode: 'markers+lines', nTraces: 1 -}, { - n: 1000, mode: 'markers', nTraces: 10 -}, { - n: 2000, mode: 'markers', nTraces: 10 -}, { - n: 4000, mode: 'markers', nTraces: 10 -}, { - n: 8000, mode: 'markers', nTraces: 10 -}, { - n: 16000, mode: 'markers', nTraces: 10 -}, { - n: 32000, mode: 'markers', nTraces: 10 -}, { - n: 64000, mode: 'markers', nTraces: 10 -}, { - n: 1000, mode: 'lines', nTraces: 10 -}, { - n: 2000, mode: 'lines', nTraces: 10 -}, { - n: 4000, mode: 'lines', nTraces: 10 -}, { - n: 8000, mode: 'lines', nTraces: 10 -}, { - n: 16000, mode: 'lines', nTraces: 10 -}, { - n: 32000, mode: 'lines', nTraces: 10 -}, { - n: 64000, mode: 'lines', nTraces: 10 -}, { - n: 1000, mode: 'markers+lines', nTraces: 10 -}, { - n: 2000, mode: 'markers+lines', nTraces: 10 -}, { - n: 4000, mode: 'markers+lines', nTraces: 10 -}, { - n: 8000, mode: 'markers+lines', nTraces: 10 -}, { - n: 16000, mode: 'markers+lines', nTraces: 10 -}, { - n: 32000, mode: 'markers+lines', nTraces: 10 -}, { - n: 64000, mode: 'markers+lines', nTraces: 10 -}, { - n: 1000, mode: 'markers', nTraces: 100 -}, { - n: 2000, mode: 'markers', nTraces: 100 -}, { - n: 4000, mode: 'markers', nTraces: 100 -}, { - n: 8000, mode: 'markers', nTraces: 100 -}, { - n: 16000, mode: 'markers', nTraces: 100 -}, { - n: 32000, mode: 'markers', nTraces: 100 -}, { - n: 64000, mode: 'markers', nTraces: 100 -}, { - n: 1000, mode: 'lines', nTraces: 100 -}, { - n: 2000, mode: 'lines', nTraces: 100 -}, { - n: 4000, mode: 'lines', nTraces: 100 -}, { - n: 8000, mode: 'lines', nTraces: 100 -}, { - n: 16000, mode: 'lines', nTraces: 100 -}, { - n: 32000, mode: 'lines', nTraces: 100 -}, { - n: 64000, mode: 'lines', nTraces: 100 -}, { - n: 1000, mode: 'markers+lines', nTraces: 100 -}, { - n: 2000, mode: 'markers+lines', nTraces: 100 -}, { - n: 4000, mode: 'markers+lines', nTraces: 100 -}, { - n: 8000, mode: 'markers+lines', nTraces: 100 -}, { - n: 16000, mode: 'markers+lines', nTraces: 100 -}, { - n: 32000, mode: 'markers+lines', nTraces: 100 -}, { - n: 64000, mode: 'markers+lines', nTraces: 100 -}]; +var tests = []; +for(let mode of ['markers', 'lines', 'markers+lines']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' scattergl | size:' + spec.n + ' | mode: ' + spec.mode, function() { diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js index 06c0f6c62c2..2688490d2ac 100644 --- a/test/jasmine/performance_tests/violin_test.js +++ b/test/jasmine/performance_tests/violin_test.js @@ -13,91 +13,18 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); const nTimes = samples.length - 1; -var tests = [{ - n: 1000, mode: 'no points', nTraces: 1 -}, { - n: 2000, mode: 'no points', nTraces: 1 -}, { - n: 4000, mode: 'no points', nTraces: 1 -}, { - n: 8000, mode: 'no points', nTraces: 1 -}, { - n: 16000, mode: 'no points', nTraces: 1 -}, { - n: 32000, mode: 'no points', nTraces: 1 -}, { - n: 64000, mode: 'no points', nTraces: 1 -}, { - n: 1000, mode: 'all points', nTraces: 1 -}, { - n: 2000, mode: 'all points', nTraces: 1 -}, { - n: 4000, mode: 'all points', nTraces: 1 -}, { - n: 8000, mode: 'all points', nTraces: 1 -}, { - n: 16000, mode: 'all points', nTraces: 1 -}, { - n: 32000, mode: 'all points', nTraces: 1 -}, { - n: 64000, mode: 'all points', nTraces: 1 -}, { - n: 1000, mode: 'no points', nTraces: 10 -}, { - n: 2000, mode: 'no points', nTraces: 10 -}, { - n: 4000, mode: 'no points', nTraces: 10 -}, { - n: 8000, mode: 'no points', nTraces: 10 -}, { - n: 16000, mode: 'no points', nTraces: 10 -}, { - n: 32000, mode: 'no points', nTraces: 10 -}, { - n: 64000, mode: 'no points', nTraces: 10 -}, { - n: 1000, mode: 'all points', nTraces: 10 -}, { - n: 2000, mode: 'all points', nTraces: 10 -}, { - n: 4000, mode: 'all points', nTraces: 10 -}, { - n: 8000, mode: 'all points', nTraces: 10 -}, { - n: 16000, mode: 'all points', nTraces: 10 -}, { - n: 32000, mode: 'all points', nTraces: 10 -}, { - n: 64000, mode: 'all points', nTraces: 10 -}, { - n: 1000, mode: 'no points', nTraces: 100 -}, { - n: 2000, mode: 'no points', nTraces: 100 -}, { - n: 4000, mode: 'no points', nTraces: 100 -}, { - n: 8000, mode: 'no points', nTraces: 100 -}, { - n: 16000, mode: 'no points', nTraces: 100 -}, { - n: 32000, mode: 'no points', nTraces: 100 -}, { - n: 64000, mode: 'no points', nTraces: 100 -}, { - n: 1000, mode: 'all points', nTraces: 100 -}, { - n: 2000, mode: 'all points', nTraces: 100 -}, { - n: 4000, mode: 'all points', nTraces: 100 -}, { - n: 8000, mode: 'all points', nTraces: 100 -}, { - n: 16000, mode: 'all points', nTraces: 100 -}, { - n: 32000, mode: 'all points', nTraces: 100 -}, { - n: 64000, mode: 'all points', nTraces: 100 -}]; +var tests = []; +for(let mode of['no points', 'all points']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + mode: mode, + nTraces: nTraces + }); + } + } +} tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' violin | size:' + spec.n + ' | mode: ' + spec.mode, function() { From c99d887e19bce7ea0694868eeea11aa6085ac9bb Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Mon, 23 Jun 2025 18:31:50 -0400 Subject: [PATCH 29/45] combine all tests --- .circleci/config.yml | 5 - test/jasmine/performance_tests/all_test.js | 317 ++++++++++++++++++ .../performance_tests/assets/post_process.js | 6 +- test/jasmine/performance_tests/bar_test.js | 92 ----- test/jasmine/performance_tests/box_test.js | 92 ----- .../jasmine/performance_tests/contour_test.js | 92 ----- .../jasmine/performance_tests/heatmap_test.js | 92 ----- .../performance_tests/histogram_test.js | 92 ----- test/jasmine/performance_tests/image_test.js | 99 ------ .../jasmine/performance_tests/scatter_test.js | 89 ----- .../performance_tests/scattergeo_test.js | 89 ----- .../performance_tests/scattergl_test.js | 88 ----- test/jasmine/performance_tests/violin_test.js | 92 ----- 13 files changed, 320 insertions(+), 925 deletions(-) create mode 100644 test/jasmine/performance_tests/all_test.js delete mode 100644 test/jasmine/performance_tests/bar_test.js delete mode 100644 test/jasmine/performance_tests/box_test.js delete mode 100644 test/jasmine/performance_tests/contour_test.js delete mode 100644 test/jasmine/performance_tests/heatmap_test.js delete mode 100644 test/jasmine/performance_tests/histogram_test.js delete mode 100644 test/jasmine/performance_tests/image_test.js delete mode 100644 test/jasmine/performance_tests/scatter_test.js delete mode 100644 test/jasmine/performance_tests/scattergeo_test.js delete mode 100644 test/jasmine/performance_tests/scattergl_test.js delete mode 100644 test/jasmine/performance_tests/violin_test.js diff --git a/.circleci/config.yml b/.circleci/config.yml index c1362c052e4..d79afdb0d98 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -53,11 +53,6 @@ jobs: - run: name: Run performance tests command: .circleci/test.sh performance-jasmine - - run: - name: Combine CSV files - command: | - head -n 1 `ls ~/Downloads/*.csv | head -n 1` > ~/Downloads/all.csv - tail -n+2 -q ~/Downloads/*.csv >> ~/Downloads/all.csv - run: name: Display system information command: npm run system-info > ~/Downloads/system_info.txt diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js new file mode 100644 index 00000000000..e3b75642886 --- /dev/null +++ b/test/jasmine/performance_tests/all_test.js @@ -0,0 +1,317 @@ +var createGraphDiv = require('../assets/create_graph_div'); +var delay = require('../assets/delay'); +var d3SelectAll = require('../../strict-d3').selectAll; +var Plotly = require('../../../lib/index'); +var downloadCSV = require('./assets/post_process').downloadCSV; +var nSamples = require('./assets/constants').nSamples; + +var gd = createGraphDiv(); + +const samples = Array.from({ length: nSamples }, (_, i) => i); +const nTimes = samples.length - 1; + +var tests = []; + +for(let traceType of ['image', 'heatmap', 'contour']) { + for(let m of [10, 20, 40, 80, 160, 320, 640]) { + let nx = 5 * m; + let ny = 2 * m; + tests.push({ + nx: nx, + ny: ny, + n: nx * ny, + nTraces: 1, + traceType: traceType, + selector: traceType === 'image' ? 'g.imagelayer.mlayer' : + 'g.' + traceType + 'layer' + }); + } +} + +for(let traceType of ['box', 'violin']) { + for(let mode of ['no points', 'all points']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: ( + traceType === 'box' ? 'g.trace.boxes' : + traceType === 'violin' ? 'g.trace.violins' : + undefined + ) + }); + } + } + } +} + +for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { + for(let mode of ['markers', 'lines', 'markers+lines']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: ( + traceType === 'scatter' ? 'g.trace.scatter' : + undefined + ) + }); + } + } + } +} + +for(let traceType of ['bar', 'histogram']) { + for(let mode of ['group', 'stack', 'overlay']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: 'g.trace.bars' + }); + } + } + } +} + +function generateMock(spec) { + var type = spec.traceType; + return ( + (type === 'image') ? makeImage(spec) : + (type === 'heatmap' || type === 'contour') ? makeHeatmap(spec) : + (type === 'box' || type === 'violin') ? makeBox(spec) : + (type === 'bar' || type === 'histogram') ? makeBar(spec) : + (type === 'scatter' || type === 'scattergl') ? makeScatter(spec) : + (type === 'scattergeo') ? makeScatterGeo(spec) : + {} + ); +} + + +function makeImage(spec) { + var A = spec.nx; + var B = spec.ny; + + var x = Array.from({ length: A }, (_, i) => i); + var y = Array.from({ length: B }, (_, i) => i); + var z = []; + for(var k = 0; k < B ; k++) { + z[k] = []; + for(var i = 0; i < A ; i++) { + z[k][i] = [ + Math.floor(127 * (1 + Math.cos(Math.sqrt(i)))), + 0, + Math.floor(127 * (1 + Math.cos(Math.sqrt(k)))), + ]; + } + } + + return { + data: [{ + type: 'image', + x: x, + y: y, + z: z + }], + layout: { + width: 900, + height: 400 + } + }; +} + +function makeHeatmap(spec) { + var A = spec.nx; + var B = spec.ny; + + var x = Array.from({ length: A }, (_, i) => i); + var y = Array.from({ length: B }, (_, i) => i); + var z = []; + for(var k = 0; k < B ; k++) { + z[k] = Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); + } + + return { + data: [{ + type: spec.traceType, + x: x, + y: y, + z: z + }], + layout: { + width: 900, + height: 400 + } + }; +} + +function makeBox(spec) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + var trace = { + type: spec.traceType, + boxpoints: spec.mode === 'all points' ? 'all' : false, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => k) + }; + + if(spec.traceType === 'box') { + trace.boxpoints = spec.mode === 'all points' ? 'all' : false; + } + + if(spec.traceType === 'violin') { + trace.points = spec.mode === 'all points' ? 'all' : false; + } + + data.push(trace); + } + + return { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; +} + +function makeBar(spec) { + var z = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + if(spec.traceType === 'bar') { + data.push({ + type: 'bar', + y: z.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => i) + }); + } else if(spec.traceType === 'histogram') { + data.push({ + type: 'histogram', + x: z.slice(k * nPerTrace, (k + 1) * nPerTrace), + y: Array.from({ length: nPerTrace }, (_, i) => i) + }); + } + } + + return { + data: data, + layout: { + barmode: spec.mode, + showlegend: false, + width: 900, + height: 400 + } + }; +} + +function makeScatter(spec) { + var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: spec.traceType, + mode: spec.mode, + y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + x: Array.from({ length: nPerTrace }, (_, i) => i + k * nPerTrace) + }); + } + + return { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; +} + +function makeScatterGeo(spec) { + var y = Array.from({ length: spec.n }, (_, i) => 0.001 * i * Math.cos(Math.sqrt(i))); + + var data = []; + var nPerTrace = Math.floor(spec.n / spec.nTraces); + for(var k = 0; k < spec.nTraces; k++) { + data.push({ + type: 'scattergeo', + mode: spec.mode, + lat: y.slice(k * nPerTrace, (k + 1) * nPerTrace), + lon: Array.from({ length: nPerTrace }, (_, i) => -180 + 0.005 * (i + k * nPerTrace)) + }); + } + + return { + data: data, + layout: { + showlegend: false, + width: 900, + height: 400 + } + }; +} + + +tests.forEach(function(spec, index) { + describe('Performance test ' + spec.nTraces + ' ' + spec.traceType + ' | mode: ' + spec.mode + ' | size:' + spec.n, function() { + 'use strict'; + + var startTime, endTime; + + beforeEach(function(done) { + jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; + + var mock = generateMock(spec); + + startTime = performance.now(); + + // Wait for actual rendering to complete + requestAnimationFrame(function() { + requestAnimationFrame(function() { + endTime = performance.now(); + done(); + }); + }); + + Plotly.newPlot(gd, mock); + }); + + afterEach(function(done) { + delay(100)().then(done); + }); + + samples.forEach(function(t) { + it('turn: ' + t, function() { + var delta = endTime - startTime; + + if(t === 0) { + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(spec.selector) { + var nodes = d3SelectAll(spec.selector); + expect(nodes.size()).toEqual(spec.nTraces); + } + + if(t === nTimes && index === tests.length - 1) { + downloadCSV(tests); + } + }); + }); + }); +}); diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 5172d0eb1db..b2780d2bbda 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,4 +1,4 @@ -exports.downloadCSV = function(traceName, allTests) { +exports.downloadCSV = function(allTests) { var str = [ 'number of traces', 'chart type', @@ -12,7 +12,7 @@ exports.downloadCSV = function(traceName, allTests) { for(var i = 0; i < test.raw.length; i++) { str += [ (test.nTraces || 1), - (traceName + (test.mode ? ' ' + test.mode : '')), + (test.traceType + (test.mode ? ' ' + test.mode : '')), test.n, i, test.raw[i] @@ -25,7 +25,7 @@ exports.downloadCSV = function(traceName, allTests) { var myBlob = new Blob([str], {type: 'text/plain'}) var url = window.URL.createObjectURL(myBlob); a.href = url; - a.download = traceName + '.csv'; + a.download = 'all.csv'; a.style.display = 'none'; document.body.append(a); a.click(); diff --git a/test/jasmine/performance_tests/bar_test.js b/test/jasmine/performance_tests/bar_test.js deleted file mode 100644 index 9bb3cbe911e..00000000000 --- a/test/jasmine/performance_tests/bar_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyBar = require('../../../lib/bar'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyBar); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['group', 'stack']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' bar | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'bar', - y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - x: Array.from({ length: nPerTrace }, (_, i) => i) - }); - } - - var mock = { - data: data, - layout: { - barmode: spec.mode, - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph bar traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.trace.bars'); - expect(nodes.size()).toEqual(spec.nTraces); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('bar', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/box_test.js b/test/jasmine/performance_tests/box_test.js deleted file mode 100644 index f9361df1524..00000000000 --- a/test/jasmine/performance_tests/box_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyBox = require('../../../lib/box'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyBox); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['no points', 'all points']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' box | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'box', - boxpoints: spec.mode === 'all points' ? 'all' : false, - y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - x: Array.from({ length: nPerTrace }, (_, i) => k) - }); - } - - var mock = { - data: data, - layout: { - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph box traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.trace.boxes'); - expect(nodes.size()).toEqual(spec.nTraces); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('box', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/contour_test.js b/test/jasmine/performance_tests/contour_test.js deleted file mode 100644 index 2111fd9bd44..00000000000 --- a/test/jasmine/performance_tests/contour_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyContour = require('../../../lib/contour'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyContour); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let m of [10, 20, 40, 80, 160, 320, 640]) { - let nx = 5 * m; - let ny = 2 * m; - tests.push({ - nx: nx, - ny: ny, - n: nx * ny, - }); -} - -tests.forEach(function(spec, index) { - describe('Performance test contour | size:' + spec.nx + 'X' + spec.ny, function() { - 'use strict'; - - var A = spec.nx; - var B = spec.ny; - - var x = Array.from({ length: A }, (_, i) => i); - var y = Array.from({ length: B }, (_, i) => i); - var z = []; - for(var k = 0; k < B ; k++) { - z[k] = Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); - } - - var mock = { - data: [{ - type: 'contour', - x: x, - y: y, - z: z - }], - layout: { - width: 900, - height: 400 - } - }; - - var startTime, endTime; - - beforeEach(function(done) { - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph contour traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.contourlayer'); - expect(nodes.size()).toEqual(1); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('contour', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/heatmap_test.js b/test/jasmine/performance_tests/heatmap_test.js deleted file mode 100644 index 93d8ac8c16a..00000000000 --- a/test/jasmine/performance_tests/heatmap_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyHeatmap = require('../../../lib/heatmap'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyHeatmap); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let m of [10, 20, 40, 80, 160, 320, 640]) { - let nx = 5 * m; - let ny = 2 * m; - tests.push({ - nx: nx, - ny: ny, - n: nx * ny, - }); -} - -tests.forEach(function(spec, index) { - describe('Performance test heatmap | size:' + spec.nx + 'X' + spec.ny, function() { - 'use strict'; - - var A = spec.nx; - var B = spec.ny; - - var x = Array.from({ length: A }, (_, i) => i); - var y = Array.from({ length: B }, (_, i) => i); - var z = []; - for(var k = 0; k < B ; k++) { - z[k] = Array.from({ length: A }, (_, i) => k * Math.cos(Math.sqrt(i))); - } - - var mock = { - data: [{ - type: 'heatmap', - x: x, - y: y, - z: z - }], - layout: { - width: 900, - height: 400 - } - }; - - var startTime, endTime; - - beforeEach(function(done) { - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph heatmap traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.heatmaplayer'); - expect(nodes.size()).toEqual(1); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('heatmap', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/histogram_test.js b/test/jasmine/performance_tests/histogram_test.js deleted file mode 100644 index 66a03e613f7..00000000000 --- a/test/jasmine/performance_tests/histogram_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyHistogram = require('../../../lib/histogram'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyHistogram); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['group', 'stack']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' histogram | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var z = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'histogram', - x: z.slice(k * nPerTrace, (k + 1) * nPerTrace), - y: Array.from({ length: nPerTrace }, (_, i) => i) - }); - } - - var mock = { - data: data, - layout: { - barmode: spec.mode, - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph histogram traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.trace.bars'); - expect(nodes.size()).toEqual(spec.nTraces); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('histogram', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/image_test.js b/test/jasmine/performance_tests/image_test.js deleted file mode 100644 index 3e87eec172e..00000000000 --- a/test/jasmine/performance_tests/image_test.js +++ /dev/null @@ -1,99 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyImage = require('../../../lib/image'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyImage); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let m of [10, 20, 40, 80, 160, 320, 640]) { - let nx = 5 * m; - let ny = 2 * m; - tests.push({ - nx: nx, - ny: ny, - n: nx * ny, - }); -} - -tests.forEach(function(spec, index) { - describe('Performance test image | size:' + spec.nx + 'X' + spec.ny, function() { - 'use strict'; - - var A = spec.nx; - var B = spec.ny; - - var x = Array.from({ length: A }, (_, i) => i); - var y = Array.from({ length: B }, (_, i) => i); - var z = []; - for(var k = 0; k < B ; k++) { - z[k] = []; - for(var i = 0; i < A ; i++) { - z[k][i] = [ - Math.floor(127 * (1 + Math.cos(Math.sqrt(i)))), - 0, - Math.floor(127 * (1 + Math.cos(Math.sqrt(k)))), - ]; - } - } - - var mock = { - data: [{ - type: 'image', - x: x, - y: y, - z: z - }], - layout: { - width: 900, - height: 400 - } - }; - - var startTime, endTime; - - beforeEach(function(done) { - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph image traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.imagelayer.mlayer'); - expect(nodes.size()).toEqual(1); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('image', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/scatter_test.js b/test/jasmine/performance_tests/scatter_test.js deleted file mode 100644 index 97b21112856..00000000000 --- a/test/jasmine/performance_tests/scatter_test.js +++ /dev/null @@ -1,89 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['markers', 'lines', 'markers+lines']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' scatter | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'scatter', - mode: spec.mode, - y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - x: Array.from({ length: nPerTrace }, (_, i) => i + k * nPerTrace) - }); - } - - var mock = { - data: data, - layout: { - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph scatter traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.trace.scatter'); - expect(nodes.size()).toEqual(spec.nTraces); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('scatter', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/scattergeo_test.js b/test/jasmine/performance_tests/scattergeo_test.js deleted file mode 100644 index 8c456201408..00000000000 --- a/test/jasmine/performance_tests/scattergeo_test.js +++ /dev/null @@ -1,89 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var Plotly = require('../../../lib/core'); -var PlotlyScattergeo = require('../../../lib/scattergeo'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyScattergeo); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['markers', 'lines', 'markers+lines']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' scattergeo | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => 0.001 * i * Math.cos(Math.sqrt(i))); - - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'scattergeo', - mode: spec.mode, - lat: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - lon: Array.from({ length: nPerTrace }, (_, i) => -180 + 0.005 * (i + k * nPerTrace)) - }); - } - - var mock = { - data: data, - layout: { - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph scattergeo traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('scattergeo', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/scattergl_test.js b/test/jasmine/performance_tests/scattergl_test.js deleted file mode 100644 index 05261f4e981..00000000000 --- a/test/jasmine/performance_tests/scattergl_test.js +++ /dev/null @@ -1,88 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var Plotly = require('../../../lib/core'); -var PlotlyScattergl = require('../../../lib/scattergl'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyScattergl); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of ['markers', 'lines', 'markers+lines']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' scattergl | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'scattergl', - mode: spec.mode, - y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - x: Array.from({ length: nPerTrace }, (_, i) => i + k * nPerTrace) - }); - } - - var mock = { - data: data, - layout: { - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph scattergl traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('scattergl', tests); - } - }); - }); - }); -}); diff --git a/test/jasmine/performance_tests/violin_test.js b/test/jasmine/performance_tests/violin_test.js deleted file mode 100644 index 2688490d2ac..00000000000 --- a/test/jasmine/performance_tests/violin_test.js +++ /dev/null @@ -1,92 +0,0 @@ -var createGraphDiv = require('../assets/create_graph_div'); -var delay = require('../assets/delay'); -var d3SelectAll = require('../../strict-d3').selectAll; -var Plotly = require('../../../lib/core'); -var PlotlyViolin = require('../../../lib/violin'); -var downloadCSV = require('./assets/post_process').downloadCSV; -var nSamples = require('./assets/constants').nSamples; - -Plotly.register(PlotlyViolin); - -var gd = createGraphDiv(); - -const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; - -var tests = []; -for(let mode of['no points', 'all points']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - mode: mode, - nTraces: nTraces - }); - } - } -} - -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' violin | size:' + spec.n + ' | mode: ' + spec.mode, function() { - 'use strict'; - - var startTime, endTime; - - beforeEach(function(done) { - var y = Array.from({ length: spec.n }, (_, i) => i * Math.cos(Math.sqrt(i))); - var data = []; - var nPerTrace = Math.floor(spec.n / spec.nTraces); - for(var k = 0; k < spec.nTraces; k++) { - data.push({ - type: 'violin', - points: spec.mode === 'all points' ? 'all' : false, - y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), - x: Array.from({ length: nPerTrace }, (_, i) => k) - }); - } - - var mock = { - data: data, - layout: { - showlegend: false, - width: 900, - height: 400 - } - }; - - startTime = performance.now(); - - // Wait for actual rendering to complete - requestAnimationFrame(function() { - requestAnimationFrame(function() { - endTime = performance.now(); - done(); - }); - }); - - Plotly.newPlot(gd, mock); - }); - - afterEach(function(done) { - delay(100)().then(done); - }); - - samples.forEach(function(t) { - it('should graph violin traces | turn: ' + t, function() { - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - var nodes = d3SelectAll('g.trace.violins'); - expect(nodes.size()).toEqual(spec.nTraces); - - if(t === nTimes && index === tests.length - 1) { - downloadCSV('violin', tests); - } - }); - }); - }); -}); From bcb165decbb10026735fffe982f18a4efea00d83 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 24 Jun 2025 08:02:16 -0400 Subject: [PATCH 30/45] improve tests --- test/jasmine/performance_tests/all_test.js | 33 ++++++++-------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index e3b75642886..54e61928e14 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -267,35 +267,26 @@ function makeScatterGeo(spec) { tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' ' + spec.traceType + ' | mode: ' + spec.mode + ' | size:' + spec.n, function() { + describe('Performance test ' + spec.nTraces + ' ' + spec.traceType + (spec.mode ? ' | mode: ' + spec.mode : '') + ' | size:' + spec.n, function() { 'use strict'; - var startTime, endTime; - - beforeEach(function(done) { - jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000; - - var mock = generateMock(spec); - - startTime = performance.now(); + samples.forEach(function(t) { + it('turn: ' + t, function() { + var startTime, endTime; - // Wait for actual rendering to complete - requestAnimationFrame(function() { requestAnimationFrame(function() { - endTime = performance.now(); - done(); + // Wait for actual rendering instead of promise + requestAnimationFrame(function() { + endTime = performance.now(); + }); }); - }); - Plotly.newPlot(gd, mock); - }); + var mock = generateMock(spec); - afterEach(function(done) { - delay(100)().then(done); - }); + startTime = performance.now(); + + Plotly.newPlot(gd, mock); - samples.forEach(function(t) { - it('turn: ' + t, function() { var delta = endTime - startTime; if(t === 0) { From b9611ae090bc09260b08d2f2fa7a0f20dbe84c5e Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 24 Jun 2025 09:43:09 -0400 Subject: [PATCH 31/45] fix time calculation --- test/jasmine/performance_tests/all_test.js | 37 ++++++++++++---------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 54e61928e14..8693964209f 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -271,13 +271,32 @@ tests.forEach(function(spec, index) { 'use strict'; samples.forEach(function(t) { - it('turn: ' + t, function() { + it('turn: ' + t, function(done) { var startTime, endTime; requestAnimationFrame(function() { // Wait for actual rendering instead of promise requestAnimationFrame(function() { endTime = performance.now(); + + var delta = endTime - startTime; + console.log(delta) + + if(t === 0) { + tests[index].raw = []; + } + tests[index].raw[t] = delta; + + if(spec.selector) { + var nodes = d3SelectAll(spec.selector); + expect(nodes.size()).toEqual(spec.nTraces); + } + + if(t === nTimes && index === tests.length - 1) { + downloadCSV(tests); + } + + done(); }); }); @@ -286,22 +305,6 @@ tests.forEach(function(spec, index) { startTime = performance.now(); Plotly.newPlot(gd, mock); - - var delta = endTime - startTime; - - if(t === 0) { - tests[index].raw = []; - } - tests[index].raw[t] = delta; - - if(spec.selector) { - var nodes = d3SelectAll(spec.selector); - expect(nodes.size()).toEqual(spec.nTraces); - } - - if(t === nTimes && index === tests.length - 1) { - downloadCSV(tests); - } }); }); }); From f6aa0aba6b708c2f0ab298d662eb8c6ec9736aee Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 24 Jun 2025 09:44:57 -0400 Subject: [PATCH 32/45] remove console.log --- test/jasmine/performance_tests/all_test.js | 1 - 1 file changed, 1 deletion(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 8693964209f..2b6dcdd62c7 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -280,7 +280,6 @@ tests.forEach(function(spec, index) { endTime = performance.now(); var delta = endTime - startTime; - console.log(delta) if(t === 0) { tests[index].raw = []; From 80ac7ae30e71aa2605d31e41d8fe38cd331bfd9f Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 24 Jun 2025 09:57:44 -0400 Subject: [PATCH 33/45] add delay between tests --- test/jasmine/performance_tests/all_test.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 2b6dcdd62c7..bb6e6408355 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -270,6 +270,10 @@ tests.forEach(function(spec, index) { describe('Performance test ' + spec.nTraces + ' ' + spec.traceType + (spec.mode ? ' | mode: ' + spec.mode : '') + ' | size:' + spec.n, function() { 'use strict'; + afterEach(function(done) { + delay(100)().then(done); + }); + samples.forEach(function(t) { it('turn: ' + t, function(done) { var startTime, endTime; From fad4b36ef35f4652e256c191a4098b472c63c3ea Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Tue, 24 Jun 2025 11:55:50 -0400 Subject: [PATCH 34/45] improve collecting csv if the last one fails --- test/jasmine/performance_tests/all_test.js | 21 ++++++++----------- .../performance_tests/assets/post_process.js | 7 +++++-- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index bb6e6408355..88f9fdcc5cc 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -8,7 +8,6 @@ var nSamples = require('./assets/constants').nSamples; var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); -const nTimes = samples.length - 1; var tests = []; @@ -51,7 +50,7 @@ for(let traceType of ['box', 'violin']) { for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { for(let mode of ['markers', 'lines', 'markers+lines']) { for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000, 64000]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { tests.push({ n:n, nTraces: nTraces, @@ -266,14 +265,16 @@ function makeScatterGeo(spec) { } -tests.forEach(function(spec, index) { - describe('Performance test ' + spec.nTraces + ' ' + spec.traceType + (spec.mode ? ' | mode: ' + spec.mode : '') + ' | size:' + spec.n, function() { - 'use strict'; +describe('Performance test various traces', function() { + 'use strict'; - afterEach(function(done) { - delay(100)().then(done); - }); + afterAll(function(done) { + downloadCSV(tests); + // delay for the download to be completed + delay(1000)().then(done) + }); + tests.forEach(function(spec, index) { samples.forEach(function(t) { it('turn: ' + t, function(done) { var startTime, endTime; @@ -295,10 +296,6 @@ tests.forEach(function(spec, index) { expect(nodes.size()).toEqual(spec.nTraces); } - if(t === nTimes && index === tests.length - 1) { - downloadCSV(tests); - } - done(); }); }); diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index b2780d2bbda..225b67d1e08 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -6,16 +6,19 @@ exports.downloadCSV = function(allTests) { 'run id', 'rendering time(ms)' ].join(',') + '\n'; + for(var k = 0; k < allTests.length; k++) { var test = allTests[k]; - for(var i = 0; i < test.raw.length; i++) { + var raw = test.raw || []; + + for(var i = 0; i < raw.length; i++) { str += [ (test.nTraces || 1), (test.traceType + (test.mode ? ' ' + test.mode : '')), test.n, i, - test.raw[i] + raw[i] ].join(',') + '\n'; } } From cd874ddf1065ad1db9a45752e77eac6b46bef2c3 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 11:18:21 -0400 Subject: [PATCH 35/45] fail rendering after 4 seconds --- test/jasmine/performance_tests/all_test.js | 30 +++++++++++++++++----- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 88f9fdcc5cc..2c3b4d1f3e6 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -4,6 +4,7 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/index'); var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; +var MAX_RENDERING_TIME = 4000; var gd = createGraphDiv(); @@ -277,31 +278,48 @@ describe('Performance test various traces', function() { tests.forEach(function(spec, index) { samples.forEach(function(t) { it('turn: ' + t, function(done) { - var startTime, endTime; + if(t === 0) { + tests[index].raw = []; + } - requestAnimationFrame(function() { + var timerID; + var requestID1, requestID2; + + var startTime, endTime; + + requestID1 = requestAnimationFrame(function() { // Wait for actual rendering instead of promise - requestAnimationFrame(function() { + requestID2 = requestAnimationFrame(function() { endTime = performance.now(); var delta = endTime - startTime; - if(t === 0) { - tests[index].raw = []; + if(tests[index].raw[t] === undefined) { + tests[index].raw[t] = delta; } - tests[index].raw[t] = delta; if(spec.selector) { var nodes = d3SelectAll(spec.selector); expect(nodes.size()).toEqual(spec.nTraces); } + clearTimeout(timerID); + done(); }); }); var mock = generateMock(spec); + timerID = setTimeout(() => { + tests[index].raw[t] = 'none'; + + cancelAnimationFrame(requestID2); + cancelAnimationFrame(requestID1); + + done.fail('Takes too much time'); + }, MAX_RENDERING_TIME); + startTime = performance.now(); Plotly.newPlot(gd, mock); From 3fd0dfc18bdb8371ec8643d7e37abefdc5fbf3c7 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 11:50:43 -0400 Subject: [PATCH 36/45] add test descriptions --- test/jasmine/performance_tests/all_test.js | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 2c3b4d1f3e6..e5aa61ec614 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -4,7 +4,7 @@ var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/index'); var downloadCSV = require('./assets/post_process').downloadCSV; var nSamples = require('./assets/constants').nSamples; -var MAX_RENDERING_TIME = 4000; +var MAX_RENDERING_TIME = 4000; var gd = createGraphDiv(); @@ -275,9 +275,17 @@ describe('Performance test various traces', function() { delay(1000)().then(done) }); + afterEach(function(done) { + // delay to avoid unexpected crash on CircleCI + delay(100)().then(done) + }); + tests.forEach(function(spec, index) { samples.forEach(function(t) { - it('turn: ' + t, function(done) { + it( + spec.nTraces + ' ' + spec.traceType + + (spec.mode ? ' | mode: ' + spec.mode : '') + + ' | size:' + spec.n + ' | turn: ' + t, function(done) { if(t === 0) { tests[index].raw = []; } @@ -285,7 +293,7 @@ describe('Performance test various traces', function() { var timerID; var requestID1, requestID2; - var startTime, endTime; + var startTime, endTime; requestID1 = requestAnimationFrame(function() { // Wait for actual rendering instead of promise @@ -312,12 +320,14 @@ describe('Performance test various traces', function() { var mock = generateMock(spec); timerID = setTimeout(() => { + endTime = performance.now(); + tests[index].raw[t] = 'none'; cancelAnimationFrame(requestID2); cancelAnimationFrame(requestID1); - done.fail('Takes too much time'); + done.fail('Takes too much time: ' + (endTime - startTime)); }, MAX_RENDERING_TIME); startTime = performance.now(); From d2baf677d7a121baf29062459516f333aa410e9e Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 12:25:43 -0400 Subject: [PATCH 37/45] delay was not helpful for passing on CI --- test/jasmine/performance_tests/all_test.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index e5aa61ec614..73ef0480fb2 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -275,11 +275,6 @@ describe('Performance test various traces', function() { delay(1000)().then(done) }); - afterEach(function(done) { - // delay to avoid unexpected crash on CircleCI - delay(100)().then(done) - }); - tests.forEach(function(spec, index) { samples.forEach(function(t) { it( From 577f7ace5467fbaa23c3078e08b10941650dbf13 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 16:53:56 -0400 Subject: [PATCH 38/45] pass arguments to isolate performance tests --- tasks/test_performance.js | 6 +- test/jasmine/karma.conf.js | 14 +++- test/jasmine/performance_tests/all_test.js | 93 ++++++++++++---------- 3 files changed, 70 insertions(+), 43 deletions(-) diff --git a/tasks/test_performance.js b/tasks/test_performance.js index 1d1c9487536..26b2cc83a1f 100644 --- a/tasks/test_performance.js +++ b/tasks/test_performance.js @@ -20,7 +20,11 @@ glob(pathToJasminePerformanceTests + '/*.js').then(function(files) { 'karma', 'start', path.join(constants.pathToRoot, 'test', 'jasmine', 'karma.conf.js'), '--performanceTest=' + path.basename(file), - '--nowatch' + '--nowatch', + '--tracesType=scattergl', + '--tracesMode=markers', + '--tracesCount=1', + '--tracesPoints=1000', ].join(' '); console.log('Running: ' + cmd); diff --git a/test/jasmine/karma.conf.js b/test/jasmine/karma.conf.js index 4653e346f44..7f24674cd7a 100644 --- a/test/jasmine/karma.conf.js +++ b/test/jasmine/karma.conf.js @@ -156,7 +156,7 @@ var hasSpecReporter = reporters.indexOf('spec') !== -1; if(!hasSpecReporter && argv.showSkipped) reporters.push('spec'); if(argv.verbose) reporters.push('verbose'); -function func(config) { +var func = function(config) { // level of logging // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG // @@ -172,8 +172,18 @@ function func(config) { level: 'debug' }; + if(isPerformanceTest) { + func.defaultConfig.client = func.defaultConfig.client || {}; + func.defaultConfig.client.testCase = { + tracesType: config.tracesType, + tracesMode: config.tracesMode, + tracesCount: config.tracesCount, + tracesPoints: config.tracesPoints, + }; + } + config.set(func.defaultConfig); -} +}; func.defaultConfig = { diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 73ef0480fb2..46b73d348e2 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -276,59 +276,72 @@ describe('Performance test various traces', function() { }); tests.forEach(function(spec, index) { - samples.forEach(function(t) { - it( - spec.nTraces + ' ' + spec.traceType + - (spec.mode ? ' | mode: ' + spec.mode : '') + - ' | size:' + spec.n + ' | turn: ' + t, function(done) { - if(t === 0) { - tests[index].raw = []; - } - - var timerID; - var requestID1, requestID2; - - var startTime, endTime; - - requestID1 = requestAnimationFrame(function() { - // Wait for actual rendering instead of promise - requestID2 = requestAnimationFrame(function() { - endTime = performance.now(); + var testIt = true; + + var testCase = __karma__.config.testCase; + + if(testCase) { + if(testCase.tracesType && testCase.tracesType !== spec.traceType) testIt = false; + if(testCase.tracesCount && testCase.tracesCount !== spec.nTraces) testIt = false; + if(testCase.tracesMode && testCase.tracesMode !== spec.mode) testIt = false; + if(testCase.tracesPoints && testCase.tracesPoints !== spec.n) testIt = false; + } + + if(testIt) { + samples.forEach(function(t) { + it( + spec.nTraces + ' ' + spec.traceType + + (spec.mode ? ' | mode: ' + spec.mode : '') + + ' | size:' + spec.n + ' | turn: ' + t, function(done) { + if(t === 0) { + tests[index].raw = []; + } + + var timerID; + var requestID1, requestID2; + + var startTime, endTime; - var delta = endTime - startTime; + requestID1 = requestAnimationFrame(function() { + // Wait for actual rendering instead of promise + requestID2 = requestAnimationFrame(function() { + endTime = performance.now(); - if(tests[index].raw[t] === undefined) { - tests[index].raw[t] = delta; - } + var delta = endTime - startTime; - if(spec.selector) { - var nodes = d3SelectAll(spec.selector); - expect(nodes.size()).toEqual(spec.nTraces); - } + if(tests[index].raw[t] === undefined) { + tests[index].raw[t] = delta; + } - clearTimeout(timerID); + if(spec.selector) { + var nodes = d3SelectAll(spec.selector); + expect(nodes.size()).toEqual(spec.nTraces); + } - done(); + clearTimeout(timerID); + + done(); + }); }); - }); - var mock = generateMock(spec); + var mock = generateMock(spec); - timerID = setTimeout(() => { - endTime = performance.now(); + timerID = setTimeout(() => { + endTime = performance.now(); - tests[index].raw[t] = 'none'; + tests[index].raw[t] = 'none'; - cancelAnimationFrame(requestID2); - cancelAnimationFrame(requestID1); + cancelAnimationFrame(requestID2); + cancelAnimationFrame(requestID1); - done.fail('Takes too much time: ' + (endTime - startTime)); - }, MAX_RENDERING_TIME); + done.fail('Takes too much time: ' + (endTime - startTime)); + }, MAX_RENDERING_TIME); - startTime = performance.now(); + startTime = performance.now(); - Plotly.newPlot(gd, mock); + Plotly.newPlot(gd, mock); + }); }); - }); + } }); }); From c8dd83b6c9e99f7c0733b3ae2f7f11ba6381d812 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 18:12:49 -0400 Subject: [PATCH 39/45] run each tests case in isolation --- tasks/test_performance.js | 46 ++++++----- test/jasmine/performance_tests/all_test.js | 81 ++----------------- .../performance_tests/assets/post_process.js | 2 +- .../performance_tests/assets/test_cases.js | 74 +++++++++++++++++ 4 files changed, 106 insertions(+), 97 deletions(-) create mode 100644 test/jasmine/performance_tests/assets/test_cases.js diff --git a/tasks/test_performance.js b/tasks/test_performance.js index 26b2cc83a1f..c1485dd71a2 100644 --- a/tasks/test_performance.js +++ b/tasks/test_performance.js @@ -13,27 +13,33 @@ var pathToJasminePerformanceTests = constants.pathToJasminePerformanceTests; * * $ npm run test-jasmine -- --performanceTest= */ + +var testCases = require('../test/jasmine/performance_tests/assets/test_cases').testCases; + glob(pathToJasminePerformanceTests + '/*.js').then(function(files) { - var tasks = files.map(function(file) { - return function(cb) { - var cmd = [ - 'karma', 'start', - path.join(constants.pathToRoot, 'test', 'jasmine', 'karma.conf.js'), - '--performanceTest=' + path.basename(file), - '--nowatch', - '--tracesType=scattergl', - '--tracesMode=markers', - '--tracesCount=1', - '--tracesPoints=1000', - ].join(' '); - - console.log('Running: ' + cmd); - - exec(cmd, function(err) { - cb(null, err); - }).stdout.pipe(process.stdout); - }; - }); + var tasks = []; + for(let file of files) { + for(let testCase of testCases) { + tasks.push(function(cb) { + var cmd = [ + 'karma', 'start', + path.join(constants.pathToRoot, 'test', 'jasmine', 'karma.conf.js'), + '--performanceTest=' + path.basename(file), + '--nowatch', + '--tracesType=' + testCase.traceType, + '--tracesMode=' + testCase.mode, + '--tracesCount=' + testCase.nTraces, + '--tracesPoints=' + testCase.n, + ].join(' '); + + console.log('Running: ' + cmd); + + exec(cmd, function(err) { + cb(null, err); + }).stdout.pipe(process.stdout); + }); + } + } runSeries(tasks, function(err, results) { if(err) throw err; diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 46b73d348e2..54d8f646881 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -3,6 +3,7 @@ var delay = require('../assets/delay'); var d3SelectAll = require('../../strict-d3').selectAll; var Plotly = require('../../../lib/index'); var downloadCSV = require('./assets/post_process').downloadCSV; +var tests = require('./assets/test_cases').testCases; var nSamples = require('./assets/constants').nSamples; var MAX_RENDERING_TIME = 4000; @@ -10,78 +11,6 @@ var gd = createGraphDiv(); const samples = Array.from({ length: nSamples }, (_, i) => i); -var tests = []; - -for(let traceType of ['image', 'heatmap', 'contour']) { - for(let m of [10, 20, 40, 80, 160, 320, 640]) { - let nx = 5 * m; - let ny = 2 * m; - tests.push({ - nx: nx, - ny: ny, - n: nx * ny, - nTraces: 1, - traceType: traceType, - selector: traceType === 'image' ? 'g.imagelayer.mlayer' : - 'g.' + traceType + 'layer' - }); - } -} - -for(let traceType of ['box', 'violin']) { - for(let mode of ['no points', 'all points']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - nTraces: nTraces, - traceType: traceType, - mode: mode, - selector: ( - traceType === 'box' ? 'g.trace.boxes' : - traceType === 'violin' ? 'g.trace.violins' : - undefined - ) - }); - } - } - } -} - -for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { - for(let mode of ['markers', 'lines', 'markers+lines']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - nTraces: nTraces, - traceType: traceType, - mode: mode, - selector: ( - traceType === 'scatter' ? 'g.trace.scatter' : - undefined - ) - }); - } - } - } -} - -for(let traceType of ['bar', 'histogram']) { - for(let mode of ['group', 'stack', 'overlay']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { - tests.push({ - n:n, - nTraces: nTraces, - traceType: traceType, - mode: mode, - selector: 'g.trace.bars' - }); - } - } - } -} function generateMock(spec) { var type = spec.traceType; @@ -161,17 +90,17 @@ function makeBox(spec) { for(var k = 0; k < spec.nTraces; k++) { var trace = { type: spec.traceType, - boxpoints: spec.mode === 'all points' ? 'all' : false, + boxpoints: spec.mode === 'all_points' ? 'all' : false, y: y.slice(k * nPerTrace, (k + 1) * nPerTrace), x: Array.from({ length: nPerTrace }, (_, i) => k) }; if(spec.traceType === 'box') { - trace.boxpoints = spec.mode === 'all points' ? 'all' : false; + trace.boxpoints = spec.mode === 'all_points' ? 'all' : false; } if(spec.traceType === 'violin') { - trace.points = spec.mode === 'all points' ? 'all' : false; + trace.points = spec.mode === 'all_points' ? 'all' : false; } data.push(trace); @@ -283,8 +212,8 @@ describe('Performance test various traces', function() { if(testCase) { if(testCase.tracesType && testCase.tracesType !== spec.traceType) testIt = false; if(testCase.tracesCount && testCase.tracesCount !== spec.nTraces) testIt = false; - if(testCase.tracesMode && testCase.tracesMode !== spec.mode) testIt = false; if(testCase.tracesPoints && testCase.tracesPoints !== spec.n) testIt = false; + if((testCase.tracesMode !== 'undefined' && testCase.tracesMode) && testCase.tracesMode !== spec.mode) testIt = false; } if(testIt) { diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 225b67d1e08..71158f3ba78 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -28,7 +28,7 @@ exports.downloadCSV = function(allTests) { var myBlob = new Blob([str], {type: 'text/plain'}) var url = window.URL.createObjectURL(myBlob); a.href = url; - a.download = 'all.csv'; + a.download = 'results.csv'; a.style.display = 'none'; document.body.append(a); a.click(); diff --git a/test/jasmine/performance_tests/assets/test_cases.js b/test/jasmine/performance_tests/assets/test_cases.js new file mode 100644 index 00000000000..b8f24b0f145 --- /dev/null +++ b/test/jasmine/performance_tests/assets/test_cases.js @@ -0,0 +1,74 @@ +var tests = []; + +for(let traceType of ['image', 'heatmap', 'contour']) { + for(let m of [10, 20, 40, 80, 160, 320, 640]) { + let nx = 5 * m; + let ny = 2 * m; + tests.push({ + nx: nx, + ny: ny, + n: nx * ny, + nTraces: 1, + traceType: traceType, + selector: traceType === 'image' ? 'g.imagelayer.mlayer' : + 'g.' + traceType + 'layer' + }); + } +} + +for(let traceType of ['box', 'violin']) { + for(let mode of ['no_points', 'all_points']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: ( + traceType === 'box' ? 'g.trace.boxes' : + traceType === 'violin' ? 'g.trace.violins' : + undefined + ) + }); + } + } + } +} + +for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { + for(let mode of ['markers', 'lines', 'markers+lines']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: ( + traceType === 'scatter' ? 'g.trace.scatter' : + undefined + ) + }); + } + } + } +} + +for(let traceType of ['bar', 'histogram']) { + for(let mode of ['group', 'stack', 'overlay']) { + for(let nTraces of [1, 10, 100]) { + for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + tests.push({ + n:n, + nTraces: nTraces, + traceType: traceType, + mode: mode, + selector: 'g.trace.bars' + }); + } + } + } +} + +exports.testCases = tests; From 99e9efd2e25c5de93c585a9c8024352732647f52 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 19:17:34 -0400 Subject: [PATCH 40/45] organise output files --- .circleci/config.yml | 5 ++++ test/jasmine/performance_tests/all_test.js | 29 +++++++++++++++---- .../performance_tests/assets/post_process.js | 4 +-- 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index d79afdb0d98..38ce2d5842a 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -56,6 +56,11 @@ jobs: - run: name: Display system information command: npm run system-info > ~/Downloads/system_info.txt + - run: + name: Combine CSV files + command: | + head -n 1 `ls ~/Downloads/*.csv | head -n 1` > ~/Downloads/all.csv + tail -n+2 -q ~/Downloads/*.csv >> ~/Downloads/all.csv - store_artifacts: path: ~/Downloads destination: / diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index 54d8f646881..c62bb15306c 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -198,8 +198,10 @@ function makeScatterGeo(spec) { describe('Performance test various traces', function() { 'use strict'; + var filename; + afterAll(function(done) { - downloadCSV(tests); + downloadCSV(tests, filename); // delay for the download to be completed delay(1000)().then(done) }); @@ -209,11 +211,28 @@ describe('Performance test various traces', function() { var testCase = __karma__.config.testCase; + filename = ''; + if(testCase) { - if(testCase.tracesType && testCase.tracesType !== spec.traceType) testIt = false; - if(testCase.tracesCount && testCase.tracesCount !== spec.nTraces) testIt = false; - if(testCase.tracesPoints && testCase.tracesPoints !== spec.n) testIt = false; - if((testCase.tracesMode !== 'undefined' && testCase.tracesMode) && testCase.tracesMode !== spec.mode) testIt = false; + if(testCase.tracesType) { + filename += testCase.tracesType; + if(testCase.tracesType !== spec.traceType) testIt = false; + } + + if(testCase.tracesMode && testCase.tracesMode !== 'undefined') { + filename += '_' + testCase.tracesMode; + if(testCase.tracesMode !== spec.mode) testIt = false; + } + + if(testCase.tracesPoints) { + filename += '_' + testCase.tracesPoints; + if(testCase.tracesPoints !== spec.n) testIt = false; + } + + if(testCase.tracesCount) { + filename += '_' + testCase.tracesCount; + if(testCase.tracesCount !== spec.nTraces) testIt = false; + } } if(testIt) { diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 71158f3ba78..5e40729dc45 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,4 +1,4 @@ -exports.downloadCSV = function(allTests) { +exports.downloadCSV = function(allTests, filename) { var str = [ 'number of traces', 'chart type', @@ -28,7 +28,7 @@ exports.downloadCSV = function(allTests) { var myBlob = new Blob([str], {type: 'text/plain'}) var url = window.URL.createObjectURL(myBlob); a.href = url; - a.download = 'results.csv'; + a.download = (filename || 'results') + '.csv'; a.style.display = 'none'; document.body.append(a); a.click(); From d92d35647198426f6b19205eae9f2c26a88e7888 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 20:23:53 -0400 Subject: [PATCH 41/45] test extra points --- .../performance_tests/assets/test_cases.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/test/jasmine/performance_tests/assets/test_cases.js b/test/jasmine/performance_tests/assets/test_cases.js index b8f24b0f145..a0dda662c9f 100644 --- a/test/jasmine/performance_tests/assets/test_cases.js +++ b/test/jasmine/performance_tests/assets/test_cases.js @@ -1,7 +1,7 @@ var tests = []; for(let traceType of ['image', 'heatmap', 'contour']) { - for(let m of [10, 20, 40, 80, 160, 320, 640]) { + for(let m of [10, 20, 40, 80, 160, 320, 640, 1280]) { let nx = 5 * m; let ny = 2 * m; tests.push({ @@ -16,10 +16,13 @@ for(let traceType of ['image', 'heatmap', 'contour']) { } } +var allN = [/*1000, 2000, 4000, 8000, 16000, */32000, 64000, 128000]; +var allNTraces = [1/*, 10, 100*/] + for(let traceType of ['box', 'violin']) { for(let mode of ['no_points', 'all_points']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + for(let nTraces of allNTraces) { + for(let n of allN) { tests.push({ n:n, nTraces: nTraces, @@ -38,8 +41,8 @@ for(let traceType of ['box', 'violin']) { for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { for(let mode of ['markers', 'lines', 'markers+lines']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + for(let nTraces of allNTraces) { + for(let n of allN) { tests.push({ n:n, nTraces: nTraces, @@ -57,8 +60,8 @@ for(let traceType of ['scatter', 'scattergl', 'scattergeo']) { for(let traceType of ['bar', 'histogram']) { for(let mode of ['group', 'stack', 'overlay']) { - for(let nTraces of [1, 10, 100]) { - for(let n of [1000, 2000, 4000, 8000, 16000, 32000]) { + for(let nTraces of allNTraces) { + for(let n of allN) { tests.push({ n:n, nTraces: nTraces, From a98fd66eaaa004729c693ee9883e505112611d11 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Thu, 26 Jun 2025 20:44:35 -0400 Subject: [PATCH 42/45] revise test setup --- test/jasmine/performance_tests/assets/test_cases.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/jasmine/performance_tests/assets/test_cases.js b/test/jasmine/performance_tests/assets/test_cases.js index a0dda662c9f..27f86de551f 100644 --- a/test/jasmine/performance_tests/assets/test_cases.js +++ b/test/jasmine/performance_tests/assets/test_cases.js @@ -16,8 +16,8 @@ for(let traceType of ['image', 'heatmap', 'contour']) { } } -var allN = [/*1000, 2000, 4000, 8000, 16000, */32000, 64000, 128000]; -var allNTraces = [1/*, 10, 100*/] +var allN = [1000, 2000, 4000, 8000, 16000, 32000, 64000, 128000]; +var allNTraces = [1, /*10, */100] for(let traceType of ['box', 'violin']) { for(let mode of ['no_points', 'all_points']) { From ea673bc2d7017d576b645f342e13957579bc3e7a Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 27 Jun 2025 09:43:20 -0400 Subject: [PATCH 43/45] refactor test --- test/jasmine/performance_tests/all_test.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index c62bb15306c..e8095ff9f95 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -238,9 +238,10 @@ describe('Performance test various traces', function() { if(testIt) { samples.forEach(function(t) { it( - spec.nTraces + ' ' + spec.traceType + + 'All points:' + spec.n + ' | ' + + spec.nTraces + 'X' + spec.traceType + (spec.mode ? ' | mode: ' + spec.mode : '') + - ' | size:' + spec.n + ' | turn: ' + t, function(done) { + ' | turn: ' + t, function(done) { if(t === 0) { tests[index].raw = []; } @@ -250,9 +251,9 @@ describe('Performance test various traces', function() { var startTime, endTime; - requestID1 = requestAnimationFrame(function() { + requestID1 = requestAnimationFrame(() => { // Wait for actual rendering instead of promise - requestID2 = requestAnimationFrame(function() { + requestID2 = requestAnimationFrame(() => { endTime = performance.now(); var delta = endTime - startTime; From 8974efe7579b91d706b26628c63b6517afa9b185 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 27 Jun 2025 10:34:31 -0400 Subject: [PATCH 44/45] create CSV for failed cases --- tasks/test_performance.js | 60 ++++++++++++++++++- test/jasmine/performance_tests/all_test.js | 2 +- .../performance_tests/assets/post_process.js | 2 +- 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/tasks/test_performance.js b/tasks/test_performance.js index c1485dd71a2..a90a3da833d 100644 --- a/tasks/test_performance.js +++ b/tasks/test_performance.js @@ -1,3 +1,4 @@ +var fs = require('fs'); var path = require('path'); var exec = require('child_process').exec; var { glob } = require('glob'); @@ -5,6 +6,7 @@ var runSeries = require('run-series'); var constants = require('./util/constants'); var pathToJasminePerformanceTests = constants.pathToJasminePerformanceTests; +var pathToRoot = constants.pathToRoot; /** * Run all jasmine 'performance' test in series @@ -42,15 +44,67 @@ glob(pathToJasminePerformanceTests + '/*.js').then(function(files) { } runSeries(tasks, function(err, results) { - if(err) throw err; - var failed = results.filter(function(r) { return r; }); if(failed.length) { console.log('\ntest-performance summary:'); failed.forEach(function(r) { console.warn('- ' + r.cmd + ' failed'); }); console.log(''); - process.exit(1); + + // Create CSV file for failed cases + var str = [ + 'number of traces', + 'chart type & mode', + 'data points', + 'run id', + 'rendering time(ms)' + ].join(',') + '\n'; + + failed.forEach(function(r) { + // split command string frist by space then by equal to get + var cmdArgs = r.cmd.split(' ').map(part => { + return part.split('='); + }); + + var test = {}; + + for(var i = 0; i < cmdArgs.length; i++) { + if('--tracesCount' === cmdArgs[i][0]) { + test.nTraces = cmdArgs[i][1]; + } + } + + for(var i = 0; i < cmdArgs.length; i++) { + if('--tracesType' === cmdArgs[i][0]) { + test.traceType = cmdArgs[i][1]; + } + } + + for(var i = 0; i < cmdArgs.length; i++) { + if('--tracesMode' === cmdArgs[i][0]) { + test.mode = cmdArgs[i][1]; + } + } + + for(var i = 0; i < cmdArgs.length; i++) { + if('--tracesPoints' === cmdArgs[i][0]) { + test.n = cmdArgs[i][1]; + } + } + + str += [ + (test.nTraces || 1), + (test.traceType + (test.mode ? ' ' + test.mode : '')), + test.n, + 'failed', + '' + ].join(',') + '\n'; + }); + + var failedCSV = pathToRoot + '../../../Downloads/failed.csv'; + console.log('Saving:', failedCSV) + console.log(str); + fs.writeFileSync(failedCSV, str); } }); }); diff --git a/test/jasmine/performance_tests/all_test.js b/test/jasmine/performance_tests/all_test.js index e8095ff9f95..f61039b0a6a 100644 --- a/test/jasmine/performance_tests/all_test.js +++ b/test/jasmine/performance_tests/all_test.js @@ -239,7 +239,7 @@ describe('Performance test various traces', function() { samples.forEach(function(t) { it( 'All points:' + spec.n + ' | ' + - spec.nTraces + 'X' + spec.traceType + + spec.nTraces + ' X ' + spec.traceType + (spec.mode ? ' | mode: ' + spec.mode : '') + ' | turn: ' + t, function(done) { if(t === 0) { diff --git a/test/jasmine/performance_tests/assets/post_process.js b/test/jasmine/performance_tests/assets/post_process.js index 5e40729dc45..940dae12d67 100644 --- a/test/jasmine/performance_tests/assets/post_process.js +++ b/test/jasmine/performance_tests/assets/post_process.js @@ -1,7 +1,7 @@ exports.downloadCSV = function(allTests, filename) { var str = [ 'number of traces', - 'chart type', + 'chart type & mode', 'data points', 'run id', 'rendering time(ms)' From 0f80d1b15a4fb1692af08b78d7b1a09fc279ba37 Mon Sep 17 00:00:00 2001 From: Mojtaba Samimi Date: Fri, 27 Jun 2025 13:11:55 -0400 Subject: [PATCH 45/45] fix Download path --- tasks/test_performance.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tasks/test_performance.js b/tasks/test_performance.js index a90a3da833d..c029ae5fc61 100644 --- a/tasks/test_performance.js +++ b/tasks/test_performance.js @@ -101,7 +101,7 @@ glob(pathToJasminePerformanceTests + '/*.js').then(function(files) { ].join(',') + '\n'; }); - var failedCSV = pathToRoot + '../../../Downloads/failed.csv'; + var failedCSV = pathToRoot + '../Downloads/failed.csv'; console.log('Saving:', failedCSV) console.log(str); fs.writeFileSync(failedCSV, str);