1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131

build / toolchain / concurrent_links.gni [blame]

# Copyright 2016 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

# This file should only be imported from files that define toolchains.
# There's no way to enforce this exactly, but all toolchains are processed
# in the context of the default_toolchain, so we can at least check for that.
assert(current_toolchain == default_toolchain)

import("//build/config/android/config.gni")
import("//build/config/apple/symbols.gni")
import("//build/config/chromeos/ui_mode.gni")
import("//build/config/compiler/compiler.gni")
import("//build/config/coverage/coverage.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/toolchain/toolchain.gni")

declare_args() {
  # Limit the number of concurrent links; we often want to run fewer
  # links at once than we do compiles, because linking is memory-intensive.
  # The default to use varies by platform and by the amount of memory
  # available, so we call out to a script to get the right value.
  concurrent_links = -1
}

if (concurrent_links == -1) {
  if (use_thin_lto) {
    _args = [
      "--reserve_mem_gb=10",
      "--thin-lto=local",
    ]
    if (is_win) {
      # Based on measurements of linking chrome.dll and chrome_child.dll, plus
      # a little padding to account for future growth.
      _args += [ "--mem_per_link_gb=45" ]
    } else if (is_android && symbol_level == 2) {
      # Large solink of Android official builds take 30-60GB.
      _args += [ "--mem_per_link_gb=50" ]
    } else if (is_linux) {
      # OOM quite frequently for linux.
      _args += [ "--mem_per_link_gb=30" ]
    } else {
      _args += [ "--mem_per_link_gb=20" ]
    }
  } else if ((use_clang_coverage &&
              # When coverage_instrumentation_input_file is not empty it means
              # we're only instrumenting changed files and not using a lot of
              # memory. Likewise, when it's empty we're building everything with
              # coverage, which requires more memory.
              coverage_instrumentation_input_file == "") ||
             use_sanitizer_coverage || use_fuzzing_engine) {
    # Full sanitizer coverage instrumentation increases linker memory consumption
    # significantly.
    _args = [ "--mem_per_link_gb=16" ]
  } else if (is_win && symbol_level == 1 && !is_debug && is_component_build) {
    _args = [ "--mem_per_link_gb=3" ]
  } else if (is_win && target_cpu == "arm64" && !is_component_build) {
    # crbug.com/340979111: OOM quite frequently for win-arm64-rel.
    _args = [ "--mem_per_link_gb=10" ]
  } else if (is_win) {
    _args = [ "--mem_per_link_gb=6" ]
  } else if (is_mac) {
    if (enable_dsyms) {
      _args = [ "--mem_per_link_gb=12" ]
    } else {
      _args = [ "--mem_per_link_gb=4" ]
    }
  } else if (is_android && !is_component_build && symbol_level == 2) {
    # Full debug symbols require large memory for link.
    _args = [ "--mem_per_link_gb=25" ]
  } else if (is_android && !is_debug && !using_sanitizer && symbol_level < 2) {
    if (symbol_level == 1) {
      _args = [ "--mem_per_link_gb=6" ]
    } else {
      _args = [ "--mem_per_link_gb=4" ]
    }
  } else if ((is_linux || is_chromeos_lacros) && symbol_level == 0) {
    # Memory consumption on link without debug symbols is low on linux.
    _args = [ "--mem_per_link_gb=3" ]
  } else if (current_os == "zos") {
    _args = [ "--mem_per_link_gb=1" ]
  } else if (is_fuchsia) {
    # TODO(crbug.com/40854531): This was defaulting to 8GB. The number of
    #    linker instances to run in parallel is calculated by diviging
    #    the available memory by this value. On a 32GB machine with
    #    roughly 29GB of available memory, this would cause three instances
    #    to run. This started running out of memory and thrashing. This change
    #    addresses that issue to get the SDk rollers running again but
    #    could be optimized (maybe to 12GB or for different configs like
    #    component build).
    _args = [ "--mem_per_link_gb=16" ]
  } else if (is_chromeos && is_msan) {
    # crbug.com/1505350 - CrOS MSan builder consumes more memory and crushes.
    # Max 25.2GB, Avg: 9.4GB, Median: 7.9GB
    _args = [ "--mem_per_link_gb=12" ]
  } else if (is_chromeos && is_debug) {
    # b/315102033, b/312072730: Large links use 9GB-13.5GB.
    _args = [ "--mem_per_link_gb=10" ]
  } else {
    _args = []
  }

  # For Android builds, we also need to be wary of:
  # * ProGuard / R8
  # * Android Lint
  # These both have a peak usage of < 4GB, that is large enough for them to
  # need to use a pool since they both typically happen at the same time as
  # linking.
  if (is_android) {
    _args += [ "--secondary_mem_per_link=4" ]
  }

  # TODO(crbug.com/41257258) Pass more build configuration info to the script
  # so that we can compute better values.
  _command_dict = exec_script("get_concurrent_links.py", _args, "scope")

  concurrent_links = _command_dict.primary_pool_size
  concurrent_links_logs = _command_dict.explanation

  if (_command_dict.secondary_pool_size >= concurrent_links) {
    # Have R8 / Lint share the link pool unless we would safely get more
    # concurrency out of using a separate one.
    # On low-RAM machines, this allows an apk's native library to link at the
    # same time as its java is optimized with R8.
    java_cmd_pool_size = _command_dict.secondary_pool_size
  }
} else {
  assert(!use_thin_lto, "can't explicitly set concurrent_links with thinlto")
  concurrent_links_logs =
      [ "concurrent_links set by GN arg (value=$concurrent_links)" ]
}