)]}'
{
  "commit": "4fb634ebb9d07d50fd708d007cbf75d59e8094cc",
  "tree": "b19bf980008120db115f826b77af1d80ee9dd998",
  "parents": [
    "c037d83aaad33808abc5f1cce5a797ca1550cf0c"
  ],
  "author": {
    "name": "Toby Harradine",
    "email": "tobyh@canva.com",
    "time": "Mon Nov 10 11:43:36 2025 +1100"
  },
  "committer": {
    "name": "GitHub",
    "email": "noreply@github.com",
    "time": "Mon Nov 10 00:43:36 2025 +0000"
  },
  "message": "refactor: defer zip manifest building to execution phase to improve analysis phase performance (#3381)\n\nWhen py_binary/py_test were being built, they were flattening the\nrunfiles\ndepsets at analysis time in order to create the zip file mapping\nmanifest for\ntheir implicit zipapp outputs. This flattening was necessary because\nthey had\nto filter out the original main executable from the runfiles that didn\u0027t\nbelong\nin the zipapp. This flattening is expensive for large builds, in some\ncases\nadding over 400 seconds of time and significant memory overhead.\n\nTo fix, have the zip file manifest use the `runfiles_with_exe` object,\nwhich is\nthe runfiles, but pre-filtered for the files zip building doesn\u0027t want.\nThis\nthen allows passing the depsets directly to `Args.add_all` and using\nmap_each\nto transform them.\n\nAdditionally, pass `runfiles.empty_filenames` using a lambda. Accessing\nthat\nattribute implicitly flattens the runfiles.\n\nFinally, because the original profiles indicated `str.format()` was a\nnon-trivial\namount of time (46 seconds / 15% of build time), switch to using `+`\ninstead.\n\nThis is a more incremental alternative to #3380 which achieves _most_ of\nthe\nsame optimization with only Starlark changes, as opposed to introducing\nan\nexternal script written in C++.\n\n[Profile of a large\nbuild](https://github.com/user-attachments/assets/e90ae699-a04d-44df-b53c-1156aa890af5),\nwhich shows a Starlark CPU profile. It shows an overall build\ntime of 305 seconds. 46 seconds (15%) are spent in `map_zip_runfiles`,\nhalf of which\nis in `str.startswith()` and the other half in `str.format()`.\n\n---------\n\nCo-authored-by: Richard Levasseur \u003crlevasseur@google.com\u003e",
  "tree_diff": [
    {
      "type": "modify",
      "old_id": "8c472c08d8694339a39ac103aa4ed8ca5418f056",
      "old_mode": 33188,
      "old_path": "CHANGELOG.md",
      "new_id": "d7403b4f1ae82322b43ba826c54e482852d1c6b3",
      "new_mode": 33188,
      "new_path": "CHANGELOG.md"
    },
    {
      "type": "modify",
      "old_id": "1a5ad4c3c660f1ad2107e2381ee3da9da471b195",
      "old_mode": 33188,
      "old_path": "python/private/py_executable.bzl",
      "new_id": "d5c0fa5388a026aba5ee44cbe2cf30f01a1226ae",
      "new_mode": 33188,
      "new_path": "python/private/py_executable.bzl"
    }
  ]
}
