{"id":15696113,"url":"https://github.com/aminya/typescript-optimization","last_synced_at":"2025-05-08T22:44:38.234Z","repository":{"id":52406190,"uuid":"248119574","full_name":"aminya/typescript-optimization","owner":"aminya","description":"Compares different for-loops in TypeScript/JavaScript","archived":false,"fork":false,"pushed_at":"2024-03-15T00:37:34.000Z","size":1112,"stargazers_count":7,"open_issues_count":6,"forks_count":2,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-05-08T22:44:30.113Z","etag":null,"topics":["benchmark","for","for-in","for-loop","for-of","loop","optimization","typescript","typescript-optimization"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","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/aminya.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["aminya"],"polar":"aminya","patreon":"aminya"}},"created_at":"2020-03-18T02:25:32.000Z","updated_at":"2023-10-20T06:53:07.000Z","dependencies_parsed_at":"2022-08-28T18:11:47.368Z","dependency_job_id":"7e90de1c-5620-447a-bf5f-69906f6241f2","html_url":"https://github.com/aminya/typescript-optimization","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminya%2Ftypescript-optimization","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminya%2Ftypescript-optimization/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminya%2Ftypescript-optimization/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aminya%2Ftypescript-optimization/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aminya","download_url":"https://codeload.github.com/aminya/typescript-optimization/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":253160727,"owners_count":21863624,"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":["benchmark","for","for-in","for-loop","for-of","loop","optimization","typescript","typescript-optimization"],"created_at":"2024-10-03T19:07:32.026Z","updated_at":"2025-05-08T22:44:38.212Z","avatar_url":"https://github.com/aminya.png","language":"TypeScript","readme":"# TypeScript-optimization\n\nCompares different for-loops in TypeScript/JavaScript\n\nBenchmarks are done inside Node.\n\n## Summary:\n\n- Traditional `for` loops are faster.\n- Don't call functions (or lookup arrays) in the head of `for` loop\n- Define constant variables as constant\n- Use `Object.keys` for looping over objects.\n- Closure based loops (like `arr.reduce`) are very slow and should be avoided.\n- Use Transformers/compilers to transform other types of `for` to `for_traditional`\n- For string joining: `concat` is faster than `+`\n\n---\n\n### Running the benchmark\n\n```\nnpm install\nnpm run start\n```\n\n### Traditional `for` vs `for-of` vs `for-in`- Looping over Arrays\n\n- ES6 and above: the best is `for_traditional_keys`\n  Best to worst:\n  `for_traditional` \u003e `for_of` \u003e `for_in` \u003e `arr_reduce`\n\n- ES5 and lower: Both `for_traditional` and `for-of` are the best\n  Best to worst:\n  `for_traditional` == `for_of` \u003e `for_in` \u003e `arr_reduce`\n\nThis is true for array of number, string, etc, and for any array size.\n\n**ES5 Node:** if you notice, you see by targeting ES5 the TypeScript compiler converts `for-of` to the `traditional-for`, and that makes it faster than the original `for-of`!! Actually, by setting `\"downlevelIteration\": true `, you can make `for-of` slow in ES5 too!!! To fix this issue you can use `npm run build` which uses `@babel/plugin-transform-for-of` to convert `for-of` to `traditional-for` (\"loose\" is faster than \"assumeArray\").\n\n```typescript\n// Traditional\nlet sum = 0\nfor (let i = 0, l = arr.length; i \u003c l; ++i) {\n  sum += arr[i]\n}\n\n// for - of\nlet sum = 0\nfor (const a of arr) {\n  sum += a\n}\n\n// for - in\nlet sum = 0\nfor (const i in arr) {\n  sum += arr[i]\n}\n\n// arr_reduce\nlet sum = 0\nsum = arr.reduce((accumulator, currentValue) =\u003e {\n  return accumulator + currentValue\n}, sum)\n```\n\nSee the ./src for full explanation.\n\n\u003cdetails\u003e\n\u003csummary\u003eBenchmark-Result\u003c/summary\u003e\n\n    -------------------\n    ES2020:\n\n    array size of  10\n\n     number array\n\n    rank 1:  for_traditional 1,006,036.38 opts/sec (mean: 994ns, stddev: 0.001ms, 100 samples)\n    rank 2:  for_of 588,928.26 opts/sec (mean: 0.002ms, stddev: 0.002ms, 100 samples)\n    rank 3:  for_in 547,645.1 opts/sec (mean: 0.002ms, stddev: 0.005ms, 100 samples)\n    rank 4:  arr_reduce 100,020.01 opts/sec (mean: 0.01ms, stddev: 0.062ms, 100 samples)\n\n     string array\n\n    rank 1:  for_traditional_str 1,077,586.31 opts/sec (mean: 928ns, stddev: 0.001ms, 100 samples)\n    rank 2:  for_of_str 651,465.81 opts/sec (mean: 0.002ms, stddev: 0.005ms, 100 samples)\n    rank 3:  for_in_str 640,204.85 opts/sec (mean: 0.002ms, stddev: 0.003ms, 100 samples)\n    rank 4:  arr_reduce_str 178,284.91 opts/sec (mean: 0.006ms, stddev: 0.041ms, 100 samples)\n\n    -------------------\n    array size of  100\n\n     number array\n\n    rank 1:  for_traditional 344,946.54 opts/sec (mean: 0.003ms, stddev: 0.004ms, 100 samples)\n    rank 2:  for_of 100,070.05 opts/sec (mean: 0.01ms, stddev: 0.026ms, 100 samples)\n    rank 3:  for_in 98,931.54 opts/sec (mean: 0.01ms, stddev: 0.026ms, 100 samples)\n    rank 4:  arr_reduce 93,501.64 opts/sec (mean: 0.011ms, stddev: 0.051ms, 100 samples)\n\n     string array\n\n    rank 1:  for_traditional_str 282,087.44 opts/sec (mean: 0.004ms, stddev: 0.004ms, 100 samples)\n    rank 2:  for_of_str 159,108.99 opts/sec (mean: 0.006ms, stddev: 0.02ms, 100 samples)\n    rank 3:  for_in_str 84,373.95 opts/sec (mean: 0.012ms, stddev: 0.028ms, 100 samples)\n    rank 4:  arr_reduce_str 75,471.7 opts/sec (mean: 0.013ms, stddev: 0.032ms, 100 samples)\n\n    -------------------\n    array size of  1000\n\n     number array\n\n    rank 1:  for_traditional 55,193.73 opts/sec (mean: 0.018ms, stddev: 0.046ms, 100 samples)\n    rank 2:  for_of 44,591.1 opts/sec (mean: 0.022ms, stddev: 0.028ms, 100 samples)\n    rank 3:  for_in 34,046.03 opts/sec (mean: 0.029ms, stddev: 0.056ms, 100 samples)\n    rank 4:  arr_reduce 25,354.33 opts/sec (mean: 0.039ms, stddev: 0.045ms, 100 samples)\n\n     string array\n\n    rank 1:  for_traditional_str 53,934.52 opts/sec (mean: 0.019ms, stddev: 0.034ms, 100 samples)\n    rank 2:  for_of_str 45,431.83 opts/sec (mean: 0.022ms, stddev: 0.028ms, 100 samples)\n    rank 3:  for_in_str 34,488.7 opts/sec (mean: 0.029ms, stddev: 0.053ms, 100 samples)\n    rank 4:  arr_reduce_str 17,905.1 opts/sec (mean: 0.056ms, stddev: 0.06ms, 100 samples)\n\n    -------------------\n    ES5:\n\n    number array\n    array size of 1000\n    number array\n    for_traditional x 806,810 ops/sec Â±0.32% (93 runs sampled)\n    for_of x 809,966 ops/sec Â±0.28% (97 runs sampled)\n    for_in x 27,447 ops/sec Â±0.41% (96 runs sampled)\n    arr_reduce x 1,093,011 ops/sec ±57.46% (95 runs sampled)\n    Fastest is for_of\n\n    string array\n    for_traditional_str x 158,800 ops/sec ±0.73% (92 runs sampled)\n    for_of_str x 160,705 ops/sec ±0.38% (90 runs sampled)\n    for_in_str x 25,161 ops/sec ±0.43% (95 runs sampled)\n    arr_reduce_str x 155,332 ops/sec ±3.94% (94 runs sampled)\n    Fastest is for_of_str,arr_reduce_str\n\n\u003c/details\u003e\n\n### Traditional `for` optimization\n\n- in all versions: first three loop are about the same. Full array lookup in the `for-head` is very slow.\n\n```typescript\n// for-traditional\nconst arr = chance.n(chance.floating, arr_length)\nlet sum = 0\nfor (let i = 0, l = arr.length; i \u003c l; ++i) {\n  sum += arr[i]\n}\n\n// for-traditional-const\nconst arr = chance2.n(chance2.floating, arr_length)\nlet sum = 0\nconst l = arr.length\nfor (let i = 0; i \u003c l; ++i) {\n  sum += arr[i]\n}\n\n// for-traditional-length-lookup\nconst arr = chance3.n(chance3.floating, arr_length)\nlet sum = 0\nfor (let i = 0; i \u003c arr.length; ++i) {\n  sum += arr[i]\n}\n\n// for-traditional-array-lookup\n// to only measure its effect on calling inside the for-head\nlet sum = 0\nfor (let i = 0; i \u003c arr_return().length; ++i) {\n  sum += arr2[i] // only comparing lookup\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eBenchmark-Result\u003c/summary\u003e\n\n    ES2020:\n    -------------------\n    array size of  10\n\n     number array\n\n    rank 1:  for_traditional 41,949.83 opts/sec (mean: 0.024ms, stddev: 0.007ms, 100 samples)\n    rank 2:  for_traditional_const 20,005.6 opts/sec (mean: 0.05ms, stddev: 0.081ms, 100 samples)\n    rank 3:  for_traditional_length_lookup 18,777.58 opts/sec (mean: 0.053ms, stddev: 0.118ms, 100 samples)\n\n    -------------------\n\n    array size of  100\n\n     number array\n\n    rank 1:  for_traditional 7,183.08 opts/sec (mean: 0.139ms, stddev: 0.058ms, 100 samples)\n    rank 2:  for_traditional_const 7,168.82 opts/sec (mean: 0.139ms, stddev: 0.055ms, 100 samples)\n    rank 3:  for_traditional_length_lookup 6,961.9 opts/sec (mean: 0.144ms, stddev: 0.082ms, 100 samples)\n    rank 4:  for_traditional_full_lockup 65.56 ops/sec\n\n    -------------------\n    array size of  1000\n\n     number array\n\n    rank 1:  for_traditional 785.84 opts/sec (mean: 1.273ms, stddev: 0.16ms, 100 samples)\n    rank 2:  for_traditional_const 776.89 opts/sec (mean: 1.287ms, stddev: 0.105ms, 100 samples)\n    rank 3:  for_traditional_length_lookup 771.57 opts/sec (mean: 1.296ms, stddev: 0.172ms, 100 samples)\n    rank 4:  for_traditional_full_lockup 0.66 ops/sec\n\n    -------------------\n    ES5:\n\n    array size of 1000\n    number array\n    for_traditional x 652 ops/sec Â±0.63% (90 runs sampled)\n    for_traditional_const x 654 ops/sec Â±0.99% (91 runs sampled)\n    for_traditional_length_lookup x 651 ops/sec Â±1.00% (92 runs sampled)\n    for_traditional_full_lockup x 0.66 ops/sec Â±0.79% (6 runs sampled)\n    Fastest is for_traditional,for_traditional_const,for_traditional_length_lookup\n\n\u003c/details\u003e\n\n### `for-of` optimization\n\n- in all versions: `for_of` with array defined as `const` outside of the loop is faster.\n\n```typescript\n// for-of\n// array is made inside the function for fare comparison\nconst arr = chance.n(chance.floating, arr_length)\nlet sum = 0\nfor (const a of arr) {\n  sum += a\n}\n\n// for-of-full-array-lookup\nlet sum = 0\nfor (const a of arr_return()) {\n  sum += a\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eBenchmark-Result\u003c/summary\u003e\n\n    ES2020:\n\n    -------------------\n\n    array size of  10\n\n     number array\n\n    rank 1:  for_of 22,915.28 opts/sec (mean: 0.044ms, stddev: 0.091ms, 100 samples)\n    rank 2:  for_of_full_lookup 19,462.07 opts/sec (mean: 0.051ms, stddev: 0.095ms, 100 samples)\n\n    -------------------\n\n    array size of  100\n\n     number array\n\n    rank 1:  for_of 6,973.79 opts/sec (mean: 0.143ms, stddev: 0.063ms, 100 samples)\n    rank 2:  for_of_full_lookup 3,560.01 opts/sec (mean: 0.281ms, stddev: 0.234ms, 100 samples)\n\n    -------------------\n\n    array size of  1000\n\n     number array\n\n    rank 1:  for_of 756.4 opts/sec (mean: 1.322ms, stddev: 0.254ms, 100 samples)\n    rank 2:  for_of_full_lookup 737.15 opts/sec (mean: 1.357ms, stddev: 0.407ms, 100 samples)\n\n    -------------------\n    ES5:\n\n    array size of 1000\n    number array\n    for_of x 652 ops/sec Â±1.09% (90 runs sampled)\n    for_of_full_lookup x 654 ops/sec Â±0.75% (93 runs sampled)\n    Fastest is for_of_full_lookup,for_of\n\n\u003c/details\u003e\n\n### Traditional `for` vs `for-of` vs `for-in`- Looping over Objects\n\n- ES2020 and ES5:\n\n  - the best is `for_traditional_keys`\n\n    Best to worst:\n\n    `for_traditional_keys`\u003e `for_of_keys` \u003e `for_in` \u003e `for_of_values` \u003e `for_traditional_values` \u003e `for_of_entries`\n\n\n```typescript\nfunction for_traditional_keys(obj) {\n  let sum = \"\"\n  const keys = Object.keys(obj)\n  for (let i = 0, l = keys.length; i \u003c l; ++i) {\n    sum += obj[keys[i]]\n  }\n  return sum\n}\nfunction for_traditional_values(obj) {\n  let sum = \"\"\n  const values = Object.values(obj)\n  for (let i = 0, l = values.length; i \u003c l; ++i) {\n    sum += values[i]\n  }\n  return sum\n}\nfunction for_of_keys(obj) {\n  let sum = \"\"\n  const keys = Object.keys(obj)\n  for (const k of keys) {\n    sum += obj[k]\n  }\n  return sum\n}\nfunction for_of_entries(obj) {\n  let sum = \"\"\n  const entries = Object.entries(obj)\n  for (const [a, k] of entries) {\n    sum += a\n  }\n  return sum\n}\nfunction for_of_values(obj) {\n  let sum = \"\"\n  const values = Object.values(obj)\n  for (const value of values) {\n    sum += value\n  }\n  return sum\n}\nfunction for_in(obj) {\n  let sum = \"\"\n  for (const k in obj) {\n    sum += obj[k]\n  }\n  return sum\n}\n```\n\n\u003cdetails\u003e\n\u003csummary\u003eBenchmark-Result\u003c/summary\u003e\n\n---\n\n    ES2020:\n\n    object size of  10\n\n     obj string string\n\n    rank 1:  for_traditional_keys 1,043,841.32 opts/sec (mean: 958ns, stddev: 0.001ms, 100 samples)\n    rank 2:  for_traditional_values 668,449.12 opts/sec (mean: 0.001ms, stddev: 0.002ms, 100 samples)\n    rank 3:  for_of_keys 597,014.95 opts/sec (mean: 0.002ms, stddev: 0.005ms, 100 samples)\n    rank 4:  for_of_entries 544,959.15 opts/sec (mean: 0.002ms, stddev: 0.002ms, 100 samples)\n    rank 5:  for_of_values 183,083.12 opts/sec (mean: 0.005ms, stddev: 0.038ms, 100 samples)\n    rank 6:  for_in 113,791.53 opts/sec (mean: 0.009ms, stddev: 0.053ms, 100 samples)\n\n    object size of  17\n\n     obj string string\n\n    rank 1:  for_traditional_keys 850,340.07 opts/sec (mean: 0.001ms, stddev: 898.266ns, 100 samples)\n    rank 2:  for_traditional_values 643,086.81 opts/sec (mean: 0.002ms, stddev: 0.002ms, 100 samples)\n    rank 3:  for_of_keys 600,961.51 opts/sec (mean: 0.002ms, stddev: 0.002ms, 100 samples)\n    rank 4:  for_of_entries 221,582.1 opts/sec (mean: 0.005ms, stddev: 0.003ms, 100 samples)\n    rank 5:  for_of_values 155,666.25 opts/sec (mean: 0.006ms, stddev: 0.042ms, 100 samples)\n    rank 6:  for_in 92,395.82 opts/sec (mean: 0.011ms, stddev: 0.079ms, 100 samples)\n\n    -------------------\n\n    object size of  100\n\n     obj string string\n\n    rank 1:  for_traditional_keys 95,301.63 opts/sec (mean: 0.01ms, stddev: 0.02ms, 100 samples)\n    rank 2:  for_traditional_values 72,769.61 opts/sec (mean: 0.014ms, stddev: 0.028ms, 100 samples)\n    rank 3:  for_of_keys 70,363.07 opts/sec (mean: 0.014ms, stddev: 0.043ms, 100 samples)\n    rank 4:  for_of_entries 41,580.04 opts/sec (mean: 0.024ms, stddev: 0.031ms, 100 samples)\n    rank 5:  for_of_values 39,178.81 opts/sec (mean: 0.026ms, stddev: 0.027ms, 100 samples)\n    rank 6:  for_in 17,924.04 opts/sec (mean: 0.056ms, stddev: 0.074ms, 100 samples)\n\n    -------------------\n    object size of  1000\n\n     obj string string\n\n    rank 1:  for_traditional_keys 11,300.33 opts/sec (mean: 0.088ms, stddev: 0.034ms, 100 samples)\n    rank 2:  for_traditional_values 10,730.77 opts/sec (mean: 0.093ms, stddev: 0.088ms, 100 samples)\n    rank 3:  for_of_keys 8,409.44 opts/sec (mean: 0.119ms, stddev: 0.234ms, 100 samples)\n    rank 4:  for_of_entries 5,152.25 opts/sec (mean: 0.194ms, stddev: 0.048ms, 100 samples)\n    rank 5:  for_of_values 4,891.1 opts/sec (mean: 0.204ms, stddev: 0.062ms, 100 samples)\n    rank 6:  for_in 3,023.82 opts/sec (mean: 0.331ms, stddev: 0.14ms, 100 samples)\n\n    -------------------\n    ES5:\n\n    object size of 1000\n    obj string string\n    for_traditional_keys x 9,348 ops/sec ±0.47% (95 runs sampled)\n    for_traditional_values x 4,236 ops/sec ±0.57% (95 runs sampled)\n    for_of_keys x 9,019 ops/sec ±1.60% (90 runs sampled)\n    for_of_entries x 3,151 ops/sec ±0.20% (96 runs sampled)\n    for_of_values x 4,288 ops/sec ±0.35% (95 runs sampled)\n    for_in x 7,958 ops/sec ±0.87% (86 runs sampled)\n    Fastest is for_traditional_keys\n\n\u003c/details\u003e\n\n### String `+` vs `concat`\n\n```ts\n// concat\nsum = sum.concat(str)\n\n// +\nsum += str\n```\n\nMostly `concat` is faster than `+`\n\n\u003cdetails\u003e\n\u003csummary\u003eBenchmark-Result\u003c/summary\u003e\n```\n  -------\n\n    string length: 38\n    object size of 3\n    obj string string\n    for_traditional_keys x 13,019,511 ops/sec ±0.71% (89 runs sampled)\n    for_traditional_keys_concat x 13,068,025 ops/sec ±0.72% (90 runs sampled)\n    for_in x 30,911,643 ops/sec ±0.95% (89 runs sampled)\n    for_in_concat x 31,078,136 ops/sec ±1.31% (88 runs sampled)\n    Fastest is for_in_concat,for_in\n\n    -------\n\n    string length: 72\n    object size of 5\n    obj string string\n    for_traditional_keys x 8,173,944 ops/sec ±1.13% (88 runs sampled)\n    for_traditional_keys_concat x 8,364,054 ops/sec ±0.99% (93 runs sampled)\n    for_in x 19,812,720 ops/sec ±0.93% (92 runs sampled)\n    for_in_concat x 20,096,737 ops/sec ±0.88% (92 runs sampled)\n    Fastest is for_in_concat\n\n    -------\n\n    object size of  10\n    string length: 121\n\n     obj string string\n\n    rank 1:  for_traditional_keys 901,713.29 opts/sec (mean: 0.001ms, stddev: 0.001ms, 100 samples)\n    rank 2:  for_traditional_keys_concat 759,301.45 opts/sec (mean: 0.001ms, stddev: 0.001ms, 100 samples)\n    rank 3:  for_in 601,684.71 opts/sec (mean: 0.002ms, stddev: 0.002ms, 100 samples)\n    rank 4:  for_in_concat 200,924.25 opts/sec (mean: 0.005ms, stddev: 0.035ms, 100 samples)\n\n    -------\n\n    object size of  100\n    string length: 1194\n\n     obj string string\n\n    rank 1:  for_traditional_keys 76,155.66 opts/sec (mean: 0.013ms, stddev: 0.034ms, 100 samples)\n    rank 2:  for_traditional_keys_concat 70,402.7 opts/sec (mean: 0.014ms, stddev: 0.038ms, 100 samples)\n    rank 3:  for_in 66,480.52 opts/sec (mean: 0.015ms, stddev: 0.03ms, 100 samples)\n    rank 4:  for_in_concat 57,208.24 opts/sec (mean: 0.017ms, stddev: 0.058ms, 100 samples)\n\n    -------\n\n    object size of  1000\n    string length: 12269\n\n     obj string string\n\n    rank 1:  for_traditional_keys 11,736.81 opts/sec (mean: 0.085ms, stddev: 0.042ms, 100 samples)\n    rank 2:  for_traditional_keys_concat 11,411.1 opts/sec (mean: 0.088ms, stddev: 0.035ms, 100 samples)\n    rank 3:  for_in 11,087.46 opts/sec (mean: 0.09ms, stddev: 0.057ms, 100 samples)\n    rank 4:  for_in_concat 10,655.98 opts/sec (mean: 0.094ms, stddev: 0.042ms, 100 samples)\n\n```\n\u003c/details\u003e\n```\n","funding_links":["https://github.com/sponsors/aminya","https://polar.sh/aminya","https://patreon.com/aminya"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faminya%2Ftypescript-optimization","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faminya%2Ftypescript-optimization","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faminya%2Ftypescript-optimization/lists"}