Skip to content

Conversation

filipesilva
Copy link
Contributor

@filipesilva filipesilva commented Jan 20, 2017

Adds @ngtools/benchmark allowing the benchmark of commands via the ngbench binary.

Total command running time is tracked, and specific matches within the command output can be added i.e. the Time: 1443ms report for individual builds.

This is mostly a dev tool. Discussion is still needed to determine if it should be added.

Example usage:

  • No arguments defaults to benchmarking ng serve rebuild times (the two commands are equivalent).
kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ngbench
Base command: ng serve --no-progress
Iterations: 5

Full command: ng serve --no-progress
Time average: 16741.4
Times: 16657,16871,16897,16486,16796
Match average: 1433.2
Matches: 1443,1444,1446,1415,1418

Benchmark execution time: 83722ms

kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ngbench --command="ng serve --no-progress" --match="Time: (.*)ms" --match-count=4 --match-edit-file="src/main.ts" --match-edit-string="'benchmark string';"
Base command: ng serve --no-progress
Iterations: 5

Full command: ng serve --no-progress
Time average: 16998
Times: 17161,16904,17055,17439,16431
Match average: 1498.2
Matches: 1538,1524,1478,1458,1493

Benchmark execution time: 85002ms

  • You can select a specific command to benchmark total running time:
kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ngbench --command="ng version"
Base command: ng version
Iterations: 5

Full command: ng version
Time average: 1762.4
Times: 1711,1786,1783,1779,1753

Benchmark execution time: 8826ms
  • You can also determine a string to match in the command output
kamik@T460p MINGW64 /d/sandbox/master-project (master)
$ ngbench --command="ng build --no-progress" --match="Time: (.*)ms"
Base command: ng build --no-progress
Iterations: 5

Full command: ng build --no-progress
Time average: 10382
Times: 10118,10350,10105,10747,10590
Match average: 6723
Matches: 6490,6776,6398,7263,6688

Benchmark execution time: 51925ms

Fix #3606

@filipesilva filipesilva force-pushed the benchmark-command branch 3 times, most recently from 8daba22 to a7d4e5f Compare January 24, 2017 21:52
@filipesilva
Copy link
Contributor Author

This command should instead be a separate package.

@filipesilva filipesilva changed the title feat(benchmark): add benchmark command feat(benchmark): add benchmark package and travis job Jan 27, 2017
@filipesilva filipesilva force-pushed the benchmark-command branch 20 times, most recently from c1bfc51 to cf8d7a7 Compare February 4, 2017 00:31
@filipesilva filipesilva requested a review from hansl February 4, 2017 00:31
}

// Returns an array of `length` length, filled with `undefined`
export function makeArray(length: number) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Array.from()

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

}

// Returns average of all numbers in `arr`
export function average(arr: any[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have lodash, _.mean() would work.

import { BenchmarkOptions } from './benchmark-options';

// Log to console and logFile if it exists
export function benchmarkLog(benchmarkOptions: BenchmarkOptions, str: string) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Optional for this; could you use the @ngtools/logger library?

@@ -0,0 +1,15 @@
{
"name": "@ngtools/benchmark",
"version": "0.1.0",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you set the version to 0.0.0?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

// Returns a promise with the result of calling `times` times the `fn` function with `args`
// `fn` will be called in parallel, and is expected to return a promise
// Not used currently
export function parallelMultiPromise(times: number, fn: any, ...args: string[]) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not used?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I had it initially but there was no command that could benefit from being ran in parallel. I'll remove it.

} from './utils';

export const benchmark = (benchmarkOptions: BenchmarkOptions) => {
const log = benchmarkLog.bind(null, benchmarkOptions);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah let's use @ngtools/logger.

serialMultiPromise
} from './utils';

export const benchmark = (benchmarkOptions: BenchmarkOptions) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

export function

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

flagCombinations.unshift([]);

const startTime = Date.now();
log(`Base command: ${benchmarkOptions.command}`);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we could use a JSON.stringify, or maybe a for...in. What do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Order wouldn't be guaranteed with those, nor would they allow to show a more verbose text as easily.

childProcess.on('exit', (err: number) => {
result.time = Date.now() - startTime;
return err && !result.overrideErr
? resolve({ err, stdout, stderr })
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reject?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, still I since want to gather the remaining results. If you're doing a lot of iterations you don't want to throw everything away just because one failed.

default: [],
alias: 'ea'
},
'match': {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like these would always be the same for commands, right? Like for the serve command. I'm not sure, just wondering.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It varies a bit... on some tests I wanted to benchmark the difference in rebuilds between the main chunk and lazy loaded chunks. Or to check the rebuild time for css/html. In those cases the written string also changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added css/html/script tests

@hansl
Copy link
Contributor

hansl commented Feb 5, 2017

In case you're missing it or never saw it: https://lodash.com/docs/

@filipesilva
Copy link
Contributor Author

@hansl can you elaborate on which parts could do with being replaced with lodash? Seems excessive to add it just to replace average() and isNumber().

@filipesilva filipesilva force-pushed the benchmark-command branch 3 times, most recently from 3d85107 to b0194a4 Compare February 8, 2017 19:45
@filipesilva filipesilva force-pushed the benchmark-command branch 2 times, most recently from 08df4c2 to 2e534e5 Compare February 9, 2017 09:53
@filipesilva filipesilva force-pushed the benchmark-command branch 3 times, most recently from b593948 to 2691389 Compare February 17, 2017 19:26
@filipesilva filipesilva deleted the benchmark-command branch February 25, 2017 11:13
@filipesilva filipesilva restored the benchmark-command branch February 25, 2017 11:15
@filipesilva filipesilva reopened this Feb 25, 2017
@hansl
Copy link
Contributor

hansl commented May 22, 2017

Since we're never going to publish this, it should live in tools/bench instead of packages. thanks

@filipesilva filipesilva force-pushed the benchmark-command branch 4 times, most recently from 9ce843f to 31286cb Compare May 23, 2017 11:21
Adds `tools/bench` allowing the benchmark of commands via the `ngbench` binary in development environments.
@filipesilva
Copy link
Contributor Author

@hansl done.

@hansl hansl removed their assignment Feb 8, 2018
@hansl hansl closed this Feb 22, 2018
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Sep 12, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add daily benchmark job to travis
3 participants