aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java41
-rw-r--r--src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java1
-rw-r--r--src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java15
3 files changed, 56 insertions, 1 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java b/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
index 5a6303a16b..f7bae31dcc 100644
--- a/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
+++ b/src/main/java/com/google/devtools/build/lib/actions/ResourceManager.java
@@ -21,7 +21,10 @@ import com.google.common.base.Preconditions;
import com.google.devtools.build.lib.concurrent.ThreadSafety.ThreadSafe;
import com.google.devtools.build.lib.profiler.AutoProfiler;
import com.google.devtools.build.lib.profiler.ProfilerTask;
+import com.google.devtools.build.lib.unix.ProcMeminfoParser;
+import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.util.Pair;
+import java.io.IOException;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
@@ -146,6 +149,9 @@ public class ResourceManager {
public static final int DEFAULT_RAM_UTILIZATION_PERCENTAGE = 67;
private int ramUtilizationPercentage = DEFAULT_RAM_UTILIZATION_PERCENTAGE;
+ // Determines if local memory estimates are used.
+ private boolean localMemoryEstimate = false;
+
private ResourceManager() {
requestList = new LinkedList<>();
}
@@ -193,6 +199,14 @@ public class ResourceManager {
}
/**
+ * If set to true, then resource acquisition will query the currently available memory, rather
+ * than counting it against the fixed maximum size.
+ */
+ public void setUseLocalMemoryEstimate(boolean value) {
+ localMemoryEstimate = value;
+ }
+
+ /**
* Acquires requested resource set. Will block if resource is not available.
* NB! This method must be thread-safe!
*/
@@ -392,6 +406,31 @@ public class ResourceManager {
double availableIo = availableResources.getIoUsage();
int availableLocalTestCount = availableResources.getLocalTestCount();
+ double remainingRam = availableRam - usedRam;
+
+ if (localMemoryEstimate && OS.getCurrent() == OS.LINUX) {
+ try {
+ ProcMeminfoParser memInfo = new ProcMeminfoParser();
+ double totalFreeRam = memInfo.getFreeRamKb() / 1024;
+ double reserveMemory =
+ staticResources.getMemoryMb() * (100.0 - this.ramUtilizationPercentage) / 100.0;
+ remainingRam = totalFreeRam - reserveMemory;
+ } catch (IOException e) {
+ // If we get an error trying to determine the currently free
+ // system memory for any reason, just continue on. It is not
+ // terribly clear what could cause this, aside from an
+ // unexpected ABI breakage in the linux kernel or an OS-level
+ // misconfiguration such as not having permissions to read
+ // /proc/meminfo.
+ //
+ // remainingRam is initialized to a value that results in
+ // behavior as if localMemoryEstimate was disabled.
+ } catch (ProcMeminfoParser.KeywordNotFoundException e) {
+ // Similarly fall back to the non-localMemoryEstimate
+ // behavior.
+ }
+ }
+
// Resources are considered available if any one of the conditions below is true:
// 1) If resource is not requested at all, it is available.
// 2) If resource is not used at the moment, it is considered to be
@@ -400,7 +439,7 @@ public class ResourceManager {
// resources even if it requests more than available.
// 3) If used resource amount is less than total available resource amount.
boolean cpuIsAvailable = cpu == 0.0 || usedCpu == 0.0 || usedCpu + cpu <= availableCpu;
- boolean ramIsAvailable = ram == 0.0 || usedRam == 0.0 || usedRam + ram <= availableRam;
+ boolean ramIsAvailable = ram == 0.0 || usedRam == 0.0 || ram <= remainingRam;
boolean ioIsAvailable = io == 0.0 || usedIo == 0.0 || usedIo + io <= availableIo;
boolean localTestCountIsAvailable = localTestCount == 0 || usedLocalTestCount == 0
|| usedLocalTestCount + localTestCount <= availableLocalTestCount;
diff --git a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
index 6971aaca39..cb058474a4 100644
--- a/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
+++ b/src/main/java/com/google/devtools/build/lib/buildtool/ExecutionTool.java
@@ -630,6 +630,7 @@ public class ExecutionTool {
resources = LocalHostCapacity.getLocalHostCapacity();
resourceMgr.setRamUtilizationPercentage(options.ramUtilizationPercentage);
}
+ resourceMgr.setUseLocalMemoryEstimate(options.localMemoryEstimate);
resourceMgr.setAvailableResources(ResourceSet.create(
resources.getMemoryMb(),
diff --git a/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java b/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
index b7f1b340bf..9f9e3351b4 100644
--- a/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
+++ b/src/main/java/com/google/devtools/build/lib/exec/ExecutionOptions.java
@@ -225,6 +225,21 @@ public class ExecutionOptions extends OptionsBase {
public ResourceSet availableResources;
@Option(
+ name = "experimental_local_memory_estimate",
+ defaultValue = "false",
+ documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,
+ effectTags = {OptionEffectTag.UNKNOWN},
+ help =
+ "Estimate the actual memory available online. "
+ + "By default, Blaze assumes most actions use a fixed amount of memory, and counts "
+ + "that against the total available system memory, regardless of how much memory is "
+ + "actually available. This option enables online estimation of how much memory is "
+ + "available at any given time, and thus does not require accurate estimation of how "
+ + "much memory a given action will take."
+ )
+ public boolean localMemoryEstimate;
+
+ @Option(
name = "local_test_jobs",
defaultValue = "0",
documentationCategory = OptionDocumentationCategory.UNCATEGORIZED,