{"id":13831916,"url":"https://github.com/itchyny/sjsp","last_synced_at":"2025-07-09T15:33:49.263Z","repository":{"id":34365168,"uuid":"38289648","full_name":"itchyny/sjsp","owner":"itchyny","description":"Simple JavaScript Profiler","archived":true,"fork":false,"pushed_at":"2020-01-31T15:54:00.000Z","size":46,"stargazers_count":234,"open_issues_count":0,"forks_count":7,"subscribers_count":12,"default_branch":"master","last_synced_at":"2024-08-05T10:19:30.598Z","etag":null,"topics":["haskell","javascript","javascript-profiler"],"latest_commit_sha":null,"homepage":"https://hackage.haskell.org/package/sjsp","language":"Haskell","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/itchyny.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-06-30T05:31:06.000Z","updated_at":"2023-09-30T18:27:54.000Z","dependencies_parsed_at":"2022-09-13T02:51:08.897Z","dependency_job_id":null,"html_url":"https://github.com/itchyny/sjsp","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Fsjsp","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Fsjsp/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Fsjsp/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/itchyny%2Fsjsp/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/itchyny","download_url":"https://codeload.github.com/itchyny/sjsp/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225565949,"owners_count":17489288,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["haskell","javascript","javascript-profiler"],"created_at":"2024-08-04T10:01:44.366Z","updated_at":"2024-11-20T13:32:02.929Z","avatar_url":"https://github.com/itchyny.png","language":"Haskell","readme":"# sjsp - Simple JavaScript Profiler\n## Why?\nThis is a JavaScript profiler, injecting profiling codes into your JavaScript files.\n\nApplications written in JavaScript are getting larger these days and more complicated.\nThere are many JavaScript Frameworks and they sometimes make us difficult to profile our applications.\nThe default profilers of the Web Browsers get useless as our applications become huge and the frameworks do tricky things.\nThe profiler sometimes lists many many functions of the frameworks.\n\nLet's get back to what we really need.\n\n#### We want to profile the code we write.\n\nIn a really simple way.\n```js\nfunction test() {\n  var start_time = Date.now(); // grab the current time at the top\n\n  // our code\n\n  log_profile(\"test\", Date.now() - start_time); // grab the current time again and log the time the function consumed.\n}\n```\n\nDo we have to write the profiling codes in all the functions by hand?\n\nOf course not.\n\nSo, here comes `sjsp`, a tool for injecting profiling codes into JavaScript files.\n\n## Installation\n### Homebrew\n```shell\nbrew install itchyny/tap/sjsp\n```\n\n### Build with stack\n```shell\ngit clone https://github.com/itchyny/sjsp\ncd sjsp\nstack install\nexport PATH=$PATH:$HOME/.local/bin\n```\n\n## Usage\n```\n $ sjsp test.js            # generates test.sjsp.js\n```\n1. Use `sjsp` command on the JavaScript files you want to profile.\n   The command `sjsp` does not break your test.js, but creates a new file.\n2. Use the generated test.sjsp.js instead of test.js\n3. Open the page with your favorite browser and look into the JavaScript console.\n   The profiling result will be reported every 10 seconds.\n\nThe profiling result will look like the following.\n```\n========== SORT BY TIME ==========\ntime: 30.202sec   count:  71      test6  test.js  (line: 31, col: 18)  function test6() {\ntime: 16.474sec   count:  41      test7  test.js  (line: 37, col: 18)  function test7() {\ntime: 15.490sec   count: 133      test4  test.js  (line: 19, col: 18)  function test4() {\ntime:  5.981sec   count: 216      test1  test.js  (line:  1, col: 18)  function test1() {\ntime:  4.375sec   count:  18      test5  test.js  (line: 25, col: 18)  function test5() {\ntime:  3.241sec   count: 512      test3  test.js  (line: 13, col: 18)  function test3() {\ntime:  0.874sec   count:  67  anonymous  test.js  (line: 49, col: 24)  setInterval(function() {\ntime:  0.808sec   count:   2      test2  test.js  (line:  7, col: 18)  function test2() {\ntime:  0.445sec   count:   2  anonymous  test.js  (line: 43, col: 23)  setTimeout(function() {\n========== SORT BY COUNT ==========\ntime:  3.241sec   count: 512      test3  test.js  (line: 13, col: 18)  function test3() {\ntime:  5.981sec   count: 216      test1  test.js  (line:  1, col: 18)  function test1() {\ntime: 15.490sec   count: 133      test4  test.js  (line: 19, col: 18)  function test4() {\ntime: 30.202sec   count:  71      test6  test.js  (line: 31, col: 18)  function test6() {\ntime:  0.874sec   count:  67  anonymous  test.js  (line: 49, col: 24)  setInterval(function() {\ntime: 16.474sec   count:  41      test7  test.js  (line: 37, col: 18)  function test7() {\ntime:  4.375sec   count:  18      test5  test.js  (line: 25, col: 18)  function test5() {\ntime:  0.808sec   count:   2      test2  test.js  (line:  7, col: 18)  function test2() {\ntime:  0.445sec   count:   2  anonymous  test.js  (line: 43, col: 23)  setTimeout(function() {\n```\nThe result is easy to read and shows the functions you have to improve the performance of.\n\n## How it works\nSuppose `test.js` looks like the following.\n```js\nfunction test() {\n  console.log('test');\n}\n```\nThe `sjsp` command generates `test.sjsp.js`.\n```js\n/* some dirty codes of sjsp */ function test() { var sjsp__state = sjsp__start(\"test.js\",1,1,\"test\",\"function test() {\");\n  console.log('test');; sjsp__end(sjsp__state);\n}\n```\nIt simply inserts `sjsp__start` and `sjsp__end` function calls at the top and\nthe end of the functions. The local variable `sjsp__state` holds the starting\ntime. It also saves the name, line number and column number of the function and\nthe whole line. When the `sjsp__end` function is called, the profiling result\nis stored.\n\nIt just inserts the two statements for each functions.\nHowever, remember that functions can be aborted with `return` statements.\nHow does it handle `return` statements?\n\nSuppose the expression which is returned by the function is heavy.\n```js\nfunction test() {  \n  return someHeavyExpression;\n}\n```\nFirstly consider the following code.\n```js\nfunction test() { var sjsp__state = sjsp__start(\"test.js\",1,1,\"test\",\"function test() {  \");  \n  return someHeavyExpression; sjsp__end(sjsp__state);\n}\n```\nUnfortunately, the `sjsp__end` function will never be called. Then what about\nplacing the function before the `return` statement?\n```js\nfunction test() { var sjsp__state = sjsp__start(\"test.js\",1,1,\"test\",\"function test() {  \");  \n  sjsp__end(sjsp__state); return someHeavyExpression;\n}\n```\nThe function will surely be called but the profiling result is not correct.\nNow, let's see how `sjsp` handles `return` statements.\n```js\nfunction test() { var sjsp__state = sjsp__start(\"test.js\",1,1,\"test\",\"function test() {  \");  \n  return (function(arguments){ var sjsp__return = someHeavyExpression; sjsp__end(sjsp__state); return sjsp__return; } ).call(this,arguments);; sjsp__end(sjsp__state);\n}\n```\nIt creates an anonymous function, captures the result and calls the function instantly.\nThis way does not break the logic and the profiling result is correct.\n\n## Author\nitchyny (https://github.com/itchyny)\n\n## License\nThis software is released under the MIT License, see LICENSE.\n","funding_links":[],"categories":["Haskell"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitchyny%2Fsjsp","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fitchyny%2Fsjsp","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fitchyny%2Fsjsp/lists"}