{"id":20479267,"url":"https://github.com/elicwhite/timing-stats","last_synced_at":"2026-06-07T15:31:23.795Z","repository":{"id":66261767,"uuid":"76440765","full_name":"elicwhite/timing-stats","owner":"elicwhite","description":"Visualize timing statistics","archived":false,"fork":false,"pushed_at":"2020-05-29T20:30:08.000Z","size":4457,"stargazers_count":4,"open_issues_count":8,"forks_count":0,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-03T22:31:07.296Z","etag":null,"topics":["build","build-tool","charts","performance","performance-monitoring","performance-visualization"],"latest_commit_sha":null,"homepage":"http://www.eli-white.com/timing-stats/","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/elicwhite.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2016-12-14T08:40:30.000Z","updated_at":"2020-02-10T11:07:33.000Z","dependencies_parsed_at":null,"dependency_job_id":"b606a258-7a18-4205-950f-cfbd83147155","html_url":"https://github.com/elicwhite/timing-stats","commit_stats":null,"previous_names":["elicwhite/timing-stats","thesavior/timing-stats"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/elicwhite/timing-stats","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elicwhite%2Ftiming-stats","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elicwhite%2Ftiming-stats/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elicwhite%2Ftiming-stats/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elicwhite%2Ftiming-stats/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/elicwhite","download_url":"https://codeload.github.com/elicwhite/timing-stats/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/elicwhite%2Ftiming-stats/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34027670,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-07T02:00:07.652Z","response_time":124,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["build","build-tool","charts","performance","performance-monitoring","performance-visualization"],"created_at":"2024-11-15T15:42:48.135Z","updated_at":"2026-06-07T15:31:23.449Z","avatar_url":"https://github.com/elicwhite.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"timing-stats\n=============\nSlow builds? Want to make it faster? timing-stats shows you the different stages of your builds to know what can be sped up. Different charts give you different information into your builds.\n\n- [timing-stats](#timing-stats)\n- [Chart Types](#chart-types)\n  * [Stacked Chart](#stacked-chart)\n  * [Gantt Chart](#gantt-chart)\n  * [Critical Path Chart](#critical-path-chart)\n- [Data Format](#data-format)\n  * [JSON Schema](#json-schema)\n  * [Full Example](#full-example)\n- [Hooking up you project](#hooking-up-you-project)\n  * [The recommended way](#the-recommended-way)\n  * [The manual way](#the-manual-way)\n    + [Saving the timestamps throughout the build](#saving-the-timestamps-throughout-the-build)\n    + [Process build timestamp data](#process-build-timestamp-data)\n    + [Measure your build](#measure-your-build)\n    + [Persist the timing data](#persist-the-timing-data)\n    + [Visualize your build](#visualize-your-build)\n  * [Integrated approaches](#integrated-approaches)\n\n# Chart Types\n## Stacked Chart\nBuilds are made up of many stages. Examples of stages include:\n\n* installing dependencies from npm\n* running a unit test\n* publishing new versions of your package.\n\nThe stacked chart shows you the time of all of these stages on top of each other so you can see how they relate and what stages take up the most time.\n\n![Stacked Chart](images/stacked_chart.png?raw=true)\n\n## Gantt Chart\nThe gantt chart shows the stages during a single build. This is probably the most valuable chart to understand what you can improve to speed up your build.\n\n![Gantt Chart](images/gantt_chart.png?raw=true)\n\n## Critical Path Chart\nWhen you have stages that run in parallel, it may not actually matter if certain stages are slow. In the above example, speeding up the linters won't improve the overall build time.\n\nIn order to visualize this information, this chart only show the stages that are on the critical path for the given build. In a completely sequential build this will be the same as the regular stacked chart. For builds that utilize parallelization, this will be much more valuable.\n\n![Critical Path Chart](images/critical_stacked_chart.png?raw=true)\n\n# Data Format\nIn order to read and support many projects and data sources, we require a specific data format. The input is a JSON array of objects. Each object represents a \"build\".\n\nA build has two parts, the build identifier and an array of stages. The identifier would likely come from your continuous integration environment. Each stage has a string name and a start and end timestamp. These timestamps should include milliseconds as they are used to figure out the ordering between parallel tasks.\n\n## JSON Schema\nThe [JSON schema](http://json-schema.org/) description of the data format is as follows.\n\n```\n{\n  \"$schema\": \"http://json-schema.org/draft-04/schema#\",\n  \"type\": \"array\",\n  \"items\": {\n    \"type\": \"object\",\n    \"properties\": {\n      \"id\": {\n        \"type\": \"integer\"\n      },\n      \"stages\": {\n        \"type\": \"array\",\n        \"items\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"stage\": {\n              \"type\": \"string\"\n            },\n            \"start\": {\n              \"type\": \"integer\"\n            },\n            \"end\": {\n              \"type\": \"integer\"\n            }\n          },\n          \"required\": [\n            \"stage\",\n            \"start\",\n            \"end\"\n          ]\n        }\n      }\n    },\n    \"required\": [\n      \"id\",\n      \"stages\"\n    ]\n  }\n}\n```\n\n## Full Example\nThis web application monitors its own build and deployment process, reporting back the timing data as the sample data for the application. You can see the JSON file for the sample data [here](sample_data.json).\n\n# Hooking up you project\nIn order to get these visualizations for your project, you need to gather the start and end times for the stages in your build. The way you do this does not matter as long as the output data is in the correct format.\n\n## The recommended way\nWe recommend using [timing-stats-cli](https://github.com/TheSavior/timing-stats-cli) for the smoothest approach to benchmark your stages.\n\n## The manual way\nAfter instrumenting a few different projects in a few different languages we have found a common approach to benchmarking stages. [timing-stats-cli](https://github.com/TheSavior/timing-stats-cli) implements this approach, but may not work for all use cases. Following the steps below, you may find an approach that works better for more complicated circumstances.\n\nThere are a few steps to gathering the data we need.\n * Save the start and end timestamps throughout the process of a build\n * At the end of the build do some processing on this data\n * Persist the data somewhere\n * Measure your build\n\n### Saving the timestamps throughout the build\nI've found the easiest way to do this is to create a simple script that will append a line to a text file. A line in this file might look something like this:\n\n```\nSTART::my stage::1481968299009\n```\n\n### Process build timestamp data\nAt the end of the build, once all of the stages have been written to the text file we want to convert the data into the final JSON form. This script should parse the lines and group the start and stop times for a given stage.\n\n### Measure your build\nNow that you have a script to process the time your stages take, we need to measure the stages. Imagine you started with a `scripts` command in your `package.json` that looks like this:\n\n```\n{\n  \"scripts\": {\n    \"style\": \"eslint\"\n  }\n}\n```\n\nWe will change this to call our timing script before and after eslint:\n\n```\n{\n  \"scripts\": {\n    \"style\": \"my-timing-script START eslint \u0026\u0026 eslint \u0026\u0026 my-timing-script STOP eslint \"\n  }\n}\n```\n### Persist the timing data\nOnce we have the timing information in the right json format, we need to save it somewhere. You may choose to upload it to something like S3 or just commit it back to the repo.\n\nThis project commits its own timing information back to the repo on successful master builds.\n\n### Visualize your build\nIf your JSON file is accessible from the internet, you can view the charts for your build by navigating to the page with the url of the json file as a query string parameter\n\n```\nhttp://www.eli-white.com/timing-stats/?json=URL_FOR_JSON_FILE\nhttp://www.eli-white.com/timing-stats/?json=https://mysite.com/timingInfo.json\n```\n\n## Integrated approaches\nMeasuring individual stages in your `package.json`, `Makefile`, or equivelent is fine for getting started. Tools can help you do this in an automated way.\n\n * [grunt-before-after-hooks](https://github.com/TheSavior/grunt-before-after-hooks) provides a way to call a script before and after each task.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felicwhite%2Ftiming-stats","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Felicwhite%2Ftiming-stats","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Felicwhite%2Ftiming-stats/lists"}