Dedupe ImmutableLists created for attribute values at the Starlark -> Blaze barrier during BUILD file evaluation.

We dedupe across all lists across all attributes of all rule instances in a single package. It's very common for multiple rules to have attributes that happen to have the same value. Blaze currently unconditionally creates a shallow copy of each list-typed attribute value, which means there's not even a way for users to write optimized BUILD/bzl code. Assume we have

  def f(x):
    ...
    # assume 'f' has no side effects

and then consider the following BUILD/bzl code

  sh_library(name = 't1', srcs = ['f1.sh'], deps = f(42))
  sh_library(name = 't2', srcs = ['f2.sh'], deps = f(42))

A thoughtful user might hope/assume Blaze optimizes this and only evaluates 'f(42)' once and only has one copy of the result of 'f(42)' in memory. Both of these thoughts are false.

So the thoughtful user might then write this "optimized" code instead

  L = f(42)
  sh_library(name = 't1', srcs = ['f1.sh'], deps = L)
  sh_library(name = 't2', srcs = ['f2.sh'], deps = L)

here, 'f(42)' will be evaluated once. but Blaze internally still has two copies of L!

There are some good reasons that Blaze unconditionally creates copies of lists. One of them is that Starlark lists are mutable. Consider

  L = f(42)
  g(L) # assume 'g' has side-effects, e.g. rule instantiation
  L.append('blah')
  g(L)

Here, the first call to 'g' definitely needs to use the initial value of L.

But, not all BUILD/bzl code is like this and it's possibly to statically determine we're in the situation where L is *not* mutated [1], and so therefore it's possible to automatically share L in an optimizing manner.

[1] To be clear, I mean "it's possible to statically determine which of the 2 following situations we're in: (i) L is *definitely not* mutated or (ii) L *might be* mutated". This entails things like alias analysis too.

RELNOTES: None
PiperOrigin-RevId: 231239991
2 files changed
tree: c2c0c8af493fd5f71f23f25eaaec652031d2a908
  1. .bazelci/
  2. examples/
  3. scripts/
  4. site/
  5. src/
  6. third_party/
  7. tools/
  8. .gitattributes
  9. .gitignore
  10. AUTHORS
  11. BUILD
  12. CHANGELOG.md
  13. CODEOWNERS
  14. combine_distfiles.py
  15. combine_distfiles_to_tar.sh
  16. compile.sh
  17. CONTRIBUTING.md
  18. CONTRIBUTORS
  19. distdir.bzl
  20. ISSUE_TEMPLATE.md
  21. LICENSE
  22. README.md
  23. WORKSPACE
README.md

Bazel

{Fast, Correct} - Choose two

Build and test software of any size, quickly and reliably.

  • Speed up your builds and tests: Bazel only rebuilds what is necessary. With advanced local and distributed caching, optimized dependency analysis and parallel execution, you get fast and incremental builds.

  • One tool, multiple languages: Build and test Java, C++, Android, iOS, Go, and a wide variety of other language platforms. Bazel runs on Windows, macOS, and Linux.

  • Scalable: Bazel helps you scale your organization, codebase, and continuous integration solution. It handles codebases of any size, in multiple repositories or a huge monorepo.

  • Extensible to your needs: Easily add support for new languages and platforms with Bazel's familiar extension language. Share and re-use language rules written by the growing Bazel community.

Getting Started

Documentation

Contributing to Bazel

See CONTRIBUTING.md

Build status

Bazel is released in ‘Beta’. See the product roadmap to learn about the path toward a stable 1.0 release.