This is an automated email from the ASF dual-hosted git repository.

cwylie pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 1578913  Add cpu/cpuset cgroup and procfs data gathering (#11763)
1578913 is described below

commit 15789137a3f257081044d141f7e92c092d73b46a
Author: Arun Ramani <[email protected]>
AuthorDate: Wed Oct 6 20:27:36 2021 -0700

    Add cpu/cpuset cgroup and procfs data gathering (#11763)
    
    * cpu/cpuset cgroup and procfs data gathering
    
    * Renames and default values
    
    * Formatting
    
    * Trigger Build
    
    * Add cgroup monitors
    
    * Return 0 if no period
    
    * Update
    
    Co-authored-by: arunramani-imply 
<[email protected]>
---
 .../druid/java/util/metrics/CgroupCpuMonitor.java  |  76 +++++++
 .../java/util/metrics/CgroupCpuSetMonitor.java     |  83 ++++++++
 .../druid/java/util/metrics/ProcFsReader.java      |  87 ++++++++
 .../druid/java/util/metrics/cgroups/Cpu.java       | 110 ++++++++++
 .../druid/java/util/metrics/cgroups/CpuSet.java    | 161 +++++++++++++++
 .../java/util/metrics/CgroupCpuMonitorTest.java    |  82 ++++++++
 .../java/util/metrics/CgroupCpuSetMonitorTest.java |  89 ++++++++
 .../druid/java/util/metrics/ProcFsReaderTest.java  |  74 +++++++
 .../java/util/metrics/cgroups/CpuSetTest.java      |  96 +++++++++
 .../druid/java/util/metrics/cgroups/CpuTest.java   |  76 +++++++
 .../druid/java/util/metrics/cgroups/TestUtils.java |  12 ++
 core/src/test/resources/boot_id                    |   1 +
 core/src/test/resources/cpu.cfs_period_us          |   1 +
 core/src/test/resources/cpu.cfs_quota_us           |   1 +
 core/src/test/resources/cpu.shares                 |   1 +
 core/src/test/resources/cpuinfo                    | 223 +++++++++++++++++++++
 core/src/test/resources/cpuset.cpus                |   1 +
 .../test/resources/cpuset.effective_cpus.complex   |   1 +
 .../test/resources/cpuset.effective_cpus.simple    |   1 +
 core/src/test/resources/cpuset.effective_mems      |   1 +
 core/src/test/resources/cpuset.mems                |   1 +
 core/src/test/resources/proc.pid.cgroup            |   2 +-
 22 files changed, 1179 insertions(+), 1 deletion(-)

diff --git 
a/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuMonitor.java 
b/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuMonitor.java
new file mode 100644
index 0000000..826465b
--- /dev/null
+++ 
b/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuMonitor.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.druid.java.util.emitter.service.ServiceEmitter;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+import org.apache.druid.java.util.metrics.cgroups.CgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.Cpu;
+
+import java.util.Map;
+
+public class CgroupCpuMonitor extends FeedDefiningMonitor
+{
+  final CgroupDiscoverer cgroupDiscoverer;
+  final Map<String, String[]> dimensions;
+
+  public CgroupCpuMonitor(CgroupDiscoverer cgroupDiscoverer, final Map<String, 
String[]> dimensions, String feed)
+  {
+    super(feed);
+    this.cgroupDiscoverer = cgroupDiscoverer;
+    this.dimensions = dimensions;
+  }
+
+  public CgroupCpuMonitor(final Map<String, String[]> dimensions, String feed)
+  {
+    this(null, dimensions, feed);
+  }
+
+  public CgroupCpuMonitor(final Map<String, String[]> dimensions)
+  {
+    this(dimensions, DEFAULT_METRICS_FEED);
+  }
+
+  public CgroupCpuMonitor()
+  {
+    this(ImmutableMap.of());
+  }
+
+  @Override
+  public boolean doMonitor(ServiceEmitter emitter)
+  {
+    final Cpu cpu = new Cpu(cgroupDiscoverer);
+    final Cpu.CpuAllocationMetric cpuSnapshot = cpu.snapshot();
+
+    final ServiceMetricEvent.Builder builder = builder();
+    MonitorUtils.addDimensionsToBuilder(builder, dimensions);
+    emitter.emit(builder.build("cgroup/cpu/shares", cpuSnapshot.getShares()));
+    emitter.emit(builder.build(
+        "cgroup/cpu/cores_quota",
+        cpuSnapshot.getPeriodUs() == 0
+        ? 0
+        : ((double) cpuSnapshot.getQuotaUs()
+          ) / cpuSnapshot.getPeriodUs()
+    ));
+
+    return true;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitor.java
 
b/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitor.java
new file mode 100644
index 0000000..43a403a
--- /dev/null
+++ 
b/core/src/main/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitor.java
@@ -0,0 +1,83 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.druid.java.util.emitter.service.ServiceEmitter;
+import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
+import org.apache.druid.java.util.metrics.cgroups.CgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.CpuSet;
+
+import java.util.Map;
+
+public class CgroupCpuSetMonitor extends FeedDefiningMonitor
+{
+  final CgroupDiscoverer cgroupDiscoverer;
+  final Map<String, String[]> dimensions;
+
+  public CgroupCpuSetMonitor(CgroupDiscoverer cgroupDiscoverer, final 
Map<String, String[]> dimensions, String feed)
+  {
+    super(feed);
+    this.cgroupDiscoverer = cgroupDiscoverer;
+    this.dimensions = dimensions;
+  }
+
+  public CgroupCpuSetMonitor(final Map<String, String[]> dimensions, String 
feed)
+  {
+    this(null, dimensions, feed);
+  }
+
+  public CgroupCpuSetMonitor(final Map<String, String[]> dimensions)
+  {
+    this(dimensions, DEFAULT_METRICS_FEED);
+  }
+
+  public CgroupCpuSetMonitor()
+  {
+    this(ImmutableMap.of());
+  }
+
+  @Override
+  public boolean doMonitor(ServiceEmitter emitter)
+  {
+    final CpuSet cpuset = new CpuSet(cgroupDiscoverer);
+    final CpuSet.CpuSetMetric cpusetSnapshot = cpuset.snapshot();
+
+    final ServiceMetricEvent.Builder builder = builder();
+    MonitorUtils.addDimensionsToBuilder(builder, dimensions);
+    emitter.emit(builder.build(
+        "cgroup/cpuset/cpu_count",
+        cpusetSnapshot.getCpuSetCpus().length
+    ));
+    emitter.emit(builder.build(
+        "cgroup/cpuset/effective_cpu_count",
+        cpusetSnapshot.getEffectiveCpuSetCpus().length
+    ));
+    emitter.emit(builder.build(
+        "cgroup/cpuset/mems_count",
+        cpusetSnapshot.getCpuSetMems().length
+    ));
+    emitter.emit(builder.build(
+        "cgroup/cpuset/effective_mems_count",
+        cpusetSnapshot.getEffectiveCpuSetMems().length
+    ));
+    return true;
+  }
+}
diff --git 
a/core/src/main/java/org/apache/druid/java/util/metrics/ProcFsReader.java 
b/core/src/main/java/org/apache/druid/java/util/metrics/ProcFsReader.java
new file mode 100644
index 0000000..1a1ca08
--- /dev/null
+++ b/core/src/main/java/org/apache/druid/java/util/metrics/ProcFsReader.java
@@ -0,0 +1,87 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import com.google.common.base.Preconditions;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.UUID;
+
+/**
+ * Fetches data from top-level procfs files for metrics.
+ */
+public class ProcFsReader
+{
+  private final File procDir;
+
+  private static final Logger LOG = new Logger(ProcFsReader.class);
+  public static final Path DEFAULT_PROC_FS_ROOT = Paths.get("/proc/");
+  private static final String BOOT_ID_PATH = "sys/kernel/random/boot_id";
+  private static final String CPUINFO_PATH = "cpuinfo";
+
+  public ProcFsReader(Path procFsRoot)
+  {
+    this.procDir = Preconditions.checkNotNull(procFsRoot, 
"procFsRoot").toFile();
+    Preconditions.checkArgument(this.procDir.isDirectory(), "Not a directory: 
[%s]", procFsRoot);
+  }
+
+  /**
+   * Reads the boot ID from the boot_id path, which is just a UUID.
+   *
+   * @return The boot UUID.
+   */
+  public UUID getBootId()
+  {
+    Path path = Paths.get(this.procDir.toString(), BOOT_ID_PATH);
+    try {
+      List<String> lines = Files.readAllLines(path);
+      return lines.stream().map(UUID::fromString).findFirst().orElse(new 
UUID(0, 0));
+    }
+    catch (IOException ex) {
+      LOG.error(ex, "Unable to read %s", path);
+      return new UUID(0, 0);
+    }
+  }
+
+  /**
+   * Reads the cpuinfo path (example in src/test/resources/cpuinfo) and
+   * counts the number of processors.
+   *
+   * @return the number of processors.
+   */
+  public long getProcessorCount()
+  {
+    Path path = Paths.get(this.procDir.toString(), CPUINFO_PATH);
+    try {
+      List<String> lines = Files.readAllLines(path);
+      return lines.stream().filter(l -> l.startsWith("processor")).count();
+    }
+    catch (IOException ex) {
+      LOG.error(ex, "Unable to read %s", path);
+      return -1L;
+    }
+  }
+}
diff --git 
a/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/Cpu.java 
b/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/Cpu.java
new file mode 100644
index 0000000..a742db2
--- /dev/null
+++ b/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/Cpu.java
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics.cgroups;
+
+import com.google.common.primitives.Longs;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * Collect CPU share and quota information from cpu cgroup files.
+ */
+public class Cpu
+{
+  private static final Logger LOG = new Logger(Cpu.class);
+  private static final String CGROUP = "cpu";
+  private static final String CPU_SHARES_FILE = "cpu.shares";
+  private static final String CPU_QUOTA_FILE = "cpu.cfs_quota_us";
+  private static final String CPU_PERIOD_FILE = "cpu.cfs_period_us";
+
+  private final CgroupDiscoverer cgroupDiscoverer;
+
+  public Cpu(CgroupDiscoverer cgroupDiscoverer)
+  {
+    this.cgroupDiscoverer = cgroupDiscoverer;
+  }
+
+  /**
+   * Take a snapshot of cpu cgroup data
+   *
+   * @return A snapshot with the data populated.
+   */
+  public CpuAllocationMetric snapshot()
+  {
+    return new CpuAllocationMetric(
+        readLongValue(CPU_SHARES_FILE, -1),
+        readLongValue(CPU_QUOTA_FILE, 0),
+        readLongValue(CPU_PERIOD_FILE, 0)
+    );
+  }
+
+  private long readLongValue(String fileName, long defaultValeue)
+  {
+    try {
+      List<String> lines = 
Files.readAllLines(Paths.get(cgroupDiscoverer.discover(CGROUP).toString(), 
fileName));
+      return 
lines.stream().map(Longs::tryParse).filter(Objects::nonNull).findFirst().orElse(defaultValeue);
+    }
+    catch (RuntimeException | IOException ex) {
+      LOG.error(ex, "Unable to fetch %s", fileName);
+      return defaultValeue;
+    }
+  }
+
+  public static class CpuAllocationMetric
+  {
+    // Maps to cpu.shares - the share of CPU given to the process
+    private final long shares;
+
+    // Maps to cpu.cfs_quota_us - the maximum time in microseconds during each 
cfs_period_us
+    // in for the current group will be allowed to run
+    private final long quotaUs;
+
+    // Maps to cpu.cfs_period_us - the duration in microseconds of each 
scheduler period, for
+    // bandwidth decisions
+    private final long periodUs;
+
+    CpuAllocationMetric(long shares, long quotaUs, long periodUs)
+    {
+      this.shares = shares;
+      this.quotaUs = quotaUs;
+      this.periodUs = periodUs;
+    }
+
+    public final long getShares()
+    {
+      return shares;
+    }
+
+    public final long getQuotaUs()
+    {
+      return quotaUs;
+    }
+
+    public final long getPeriodUs()
+    {
+      return periodUs;
+    }
+  }
+}
diff --git 
a/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/CpuSet.java 
b/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/CpuSet.java
new file mode 100644
index 0000000..31b3434
--- /dev/null
+++ b/core/src/main/java/org/apache/druid/java/util/metrics/cgroups/CpuSet.java
@@ -0,0 +1,161 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics.cgroups;
+
+import com.google.common.primitives.Ints;
+import org.apache.druid.java.util.common.logger.Logger;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.IntStream;
+
+/**
+ * Collect CPU and memory data from cpuset cgroup files.
+ */
+public class CpuSet
+{
+  private static final Logger LOG = new Logger(CpuSet.class);
+  private static final String CGROUP = "cpuset";
+  private static final String CPUS_FILE = "cpuset.cpus";
+  private static final String EFFECTIVE_CPUS_FILE = "cpuset.effective_cpus";
+  private static final String MEMS_FILE = "cpuset.mems";
+  private static final String EFFECTIVE_MEMS_FILE = "cpuset.effective_mems";
+
+  private final CgroupDiscoverer cgroupDiscoverer;
+
+  public CpuSet(CgroupDiscoverer cgroupDiscoverer)
+  {
+    this.cgroupDiscoverer = cgroupDiscoverer;
+  }
+
+  /**
+   * Take a snapshot of cpuset cgroup data
+   *
+   * @return A snapshot with the data populated.
+   */
+  public CpuSetMetric snapshot()
+  {
+    return new CpuSetMetric(
+        readCpuSetFile(CPUS_FILE),
+        readCpuSetFile(EFFECTIVE_CPUS_FILE),
+        readCpuSetFile(MEMS_FILE),
+        readCpuSetFile(EFFECTIVE_MEMS_FILE)
+    );
+  }
+
+  private int[] readCpuSetFile(String file)
+  {
+    int[] output = {};
+    try {
+      List<String> lines = Files.readAllLines(
+          Paths.get(cgroupDiscoverer.discover(CGROUP).toString(), file));
+      output = 
lines.stream().map(this::parseStringRangeToIntArray).findFirst().orElse(output);
+    }
+    catch (RuntimeException | IOException ex) {
+      LOG.error(ex, "Unable to read %s", file);
+    }
+    return output;
+  }
+
+  /**
+   * Parses the cpuset list format and outputs it as a list of CPUs. Examples:
+   * 0-4,9        # bits 0, 1, 2, 3, 4, and 9 set
+   *              # outputs [0, 1, 2, 3, 4, 9]
+   * 0-2,7,12-14  # bits 0, 1, 2, 7, 12, 13, and 14 set
+   *              # outputs [0, 1, 2, 7, 12, 13, 14]
+   *
+   * This method also works fine for memory nodes.
+   *
+   * @param line The list format cpu value
+   * @return the list of CPU IDs
+   */
+  private int[] parseStringRangeToIntArray(String line)
+  {
+    String[] cpuParts = line.split(",");
+    return Arrays.stream(cpuParts)
+       .flatMapToInt(cpuPart -> {
+         String[] bits = cpuPart.split("-");
+         if (bits.length == 2) {
+           Integer low = Ints.tryParse(bits[0]);
+           Integer high = Ints.tryParse(bits[1]);
+           if (low != null && high != null) {
+             return IntStream.rangeClosed(low, high);
+           }
+         } else if (bits.length == 1) {
+           Integer bit = Ints.tryParse(bits[0]);
+           if (bit != null) {
+             return IntStream.of(bit);
+           }
+         }
+
+         return IntStream.empty();
+       }).toArray();
+  }
+
+  public static class CpuSetMetric
+  {
+    // The list of processor IDs associated with the process
+    private final int[] cpuSetCpus;
+
+    // The list of effective/active processor IDs associated with the process
+    private final int[] effectiveCpuSetCpus;
+
+    // The list memory nodes associated with the process
+    private final int[] cpuSetMems;
+
+    // The list of effective/active memory nodes associated with the process
+    private final int[] effectiveCpuSetMems;
+
+    CpuSetMetric(
+        int[] cpuSetCpus,
+        int[] effectiveCpuSetCpus,
+        int[] cpuSetMems,
+        int[] effectiveCpuSetMems)
+    {
+      this.cpuSetCpus = cpuSetCpus;
+      this.effectiveCpuSetCpus = effectiveCpuSetCpus;
+      this.cpuSetMems = cpuSetMems;
+      this.effectiveCpuSetMems = effectiveCpuSetMems;
+    }
+
+    public int[] getCpuSetCpus()
+    {
+      return cpuSetCpus;
+    }
+
+    public int[] getEffectiveCpuSetCpus()
+    {
+      return effectiveCpuSetCpus;
+    }
+
+    public int[] getCpuSetMems()
+    {
+      return cpuSetMems;
+    }
+
+    public int[] getEffectiveCpuSetMems()
+    {
+      return effectiveCpuSetMems;
+    }
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuMonitorTest.java
 
b/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuMonitorTest.java
new file mode 100644
index 0000000..4a05f5f
--- /dev/null
+++ 
b/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuMonitorTest.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.metrics.cgroups.CgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.ProcCgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.TestUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class CgroupCpuMonitorTest
+{
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+  private File procDir;
+  private File cgroupDir;
+  private CgroupDiscoverer discoverer;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    cgroupDir = temporaryFolder.newFolder();
+    procDir = temporaryFolder.newFolder();
+    discoverer = new ProcCgroupDiscoverer(procDir.toPath());
+    TestUtils.setUpCgroups(procDir, cgroupDir);
+    final File cpuDir = new File(
+        cgroupDir,
+        
"cpu,cpuacct/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
+    );
+
+    Assert.assertTrue((cpuDir.isDirectory() && cpuDir.exists()) || 
cpuDir.mkdirs());
+    TestUtils.copyOrReplaceResource("/cpu.shares", new File(cpuDir, 
"cpu.shares"));
+    TestUtils.copyOrReplaceResource("/cpu.cfs_quota_us", new File(cpuDir, 
"cpu.cfs_quota_us"));
+    TestUtils.copyOrReplaceResource("/cpu.cfs_period_us", new File(cpuDir, 
"cpu.cfs_period_us"));
+  }
+
+  @Test
+  public void testMonitor()
+  {
+    final CgroupCpuMonitor monitor = new CgroupCpuMonitor(discoverer, 
ImmutableMap.of(), "some_feed");
+    final StubServiceEmitter emitter = new StubServiceEmitter("service", 
"host");
+    Assert.assertTrue(monitor.doMonitor(emitter));
+    final List<Event> actualEvents = emitter.getEvents();
+    Assert.assertEquals(2, actualEvents.size());
+    final Map<String, Object> sharesEvent = actualEvents.get(0).toMap();
+    final Map<String, Object> coresEvent = actualEvents.get(1).toMap();
+    Assert.assertEquals("cgroup/cpu/shares", sharesEvent.get("metric"));
+    Assert.assertEquals(1024L, sharesEvent.get("value"));
+    Assert.assertEquals("cgroup/cpu/cores_quota", coresEvent.get("metric"));
+    Assert.assertEquals(3.0D, coresEvent.get("value"));
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitorTest.java
 
b/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitorTest.java
new file mode 100644
index 0000000..c661355
--- /dev/null
+++ 
b/core/src/test/java/org/apache/druid/java/util/metrics/CgroupCpuSetMonitorTest.java
@@ -0,0 +1,89 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.druid.java.util.emitter.core.Event;
+import org.apache.druid.java.util.metrics.cgroups.CgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.ProcCgroupDiscoverer;
+import org.apache.druid.java.util.metrics.cgroups.TestUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+
+public class CgroupCpuSetMonitorTest
+{
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+  private File procDir;
+  private File cgroupDir;
+  private CgroupDiscoverer discoverer;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    cgroupDir = temporaryFolder.newFolder();
+    procDir = temporaryFolder.newFolder();
+    discoverer = new ProcCgroupDiscoverer(procDir.toPath());
+    TestUtils.setUpCgroups(procDir, cgroupDir);
+    final File cpusetDir = new File(
+        cgroupDir,
+        "cpuset/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
+    );
+    Assert.assertTrue((cpusetDir.isDirectory() && cpusetDir.exists()) || 
cpusetDir.mkdirs());
+
+    TestUtils.copyOrReplaceResource("/cpuset.cpus", new File(cpusetDir, 
"cpuset.cpus"));
+    TestUtils.copyOrReplaceResource("/cpuset.effective_cpus.complex", new 
File(cpusetDir, "cpuset.effective_cpus"));
+    TestUtils.copyOrReplaceResource("/cpuset.mems", new File(cpusetDir, 
"cpuset.mems"));
+    TestUtils.copyOrReplaceResource("/cpuset.effective_mems", new 
File(cpusetDir, "cpuset.effective_mems"));
+  }
+
+  @Test
+  public void testMonitor()
+  {
+    final CgroupCpuSetMonitor monitor = new CgroupCpuSetMonitor(discoverer, 
ImmutableMap.of(), "some_feed");
+    final StubServiceEmitter emitter = new StubServiceEmitter("service", 
"host");
+    Assert.assertTrue(monitor.doMonitor(emitter));
+    final List<Event> actualEvents = emitter.getEvents();
+    Assert.assertEquals(4, actualEvents.size());
+    final Map<String, Object> cpusEvent = actualEvents.get(0).toMap();
+    final Map<String, Object> effectiveCpusEvent = actualEvents.get(1).toMap();
+    final Map<String, Object> memsEvent = actualEvents.get(2).toMap();
+    final Map<String, Object> effectiveMemsEvent = actualEvents.get(3).toMap();
+    Assert.assertEquals("cgroup/cpuset/cpu_count", cpusEvent.get("metric"));
+    Assert.assertEquals(8, cpusEvent.get("value"));
+    Assert.assertEquals("cgroup/cpuset/effective_cpu_count", 
effectiveCpusEvent.get("metric"));
+    Assert.assertEquals(7, effectiveCpusEvent.get("value"));
+    Assert.assertEquals("cgroup/cpuset/mems_count", memsEvent.get("metric"));
+    Assert.assertEquals(4, memsEvent.get("value"));
+    Assert.assertEquals("cgroup/cpuset/effective_mems_count", 
effectiveMemsEvent.get("metric"));
+    Assert.assertEquals(1, effectiveMemsEvent.get("value"));
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/ProcFsReaderTest.java 
b/core/src/test/java/org/apache/druid/java/util/metrics/ProcFsReaderTest.java
new file mode 100644
index 0000000..0cd68d1
--- /dev/null
+++ 
b/core/src/test/java/org/apache/druid/java/util/metrics/ProcFsReaderTest.java
@@ -0,0 +1,74 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics;
+
+import org.apache.druid.java.util.metrics.cgroups.TestUtils;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
+
+public class ProcFsReaderTest
+{
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+  private File procDir;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    procDir = temporaryFolder.newFolder();
+    File kernelDir = new File(
+        procDir,
+        "sys/kernel/random"
+    );
+    Assert.assertTrue(kernelDir.mkdirs());
+    TestUtils.copyResource("/cpuinfo", new File(procDir, "cpuinfo"));
+    TestUtils.copyResource("/boot_id", new File(kernelDir, "boot_id"));
+  }
+
+  @Test
+  public void testUtilThrowsOnBadDir()
+  {
+    Assert.assertThrows(
+        IllegalArgumentException.class,
+        () -> new ProcFsReader(Paths.get(procDir + "_dummy"))
+    );
+  }
+
+  @Test
+  public void testBootId()
+  {
+    final ProcFsReader fetcher = new ProcFsReader(procDir.toPath());
+    Assert.assertEquals("ad1f0a5c-55ea-4a49-9db8-bbb0f22e2ba6", 
fetcher.getBootId().toString());
+  }
+
+  @Test
+  public void testProcessorCount()
+  {
+    final ProcFsReader fetcher = new ProcFsReader(procDir.toPath());
+    Assert.assertEquals(8, fetcher.getProcessorCount());
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuSetTest.java 
b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuSetTest.java
new file mode 100644
index 0000000..516af9e
--- /dev/null
+++ 
b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuSetTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics.cgroups;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+
+
+public class CpuSetTest
+{
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+  private CgroupDiscoverer discoverer;
+  private File cpusetDir;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    File cgroupDir = temporaryFolder.newFolder();
+    File procDir = temporaryFolder.newFolder();
+    discoverer = new ProcCgroupDiscoverer(procDir.toPath());
+    TestUtils.setUpCgroups(procDir, cgroupDir);
+    cpusetDir = new File(
+        cgroupDir,
+        "cpuset/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
+    );
+    Assert.assertTrue((cpusetDir.isDirectory() && cpusetDir.exists()) || 
cpusetDir.mkdirs());
+
+    TestUtils.copyOrReplaceResource("/cpuset.cpus", new File(cpusetDir, 
"cpuset.cpus"));
+    TestUtils.copyOrReplaceResource("/cpuset.mems", new File(cpusetDir, 
"cpuset.mems"));
+    TestUtils.copyOrReplaceResource("/cpuset.effective_mems", new 
File(cpusetDir, "cpuset.effective_mems"));
+  }
+
+  @Test
+  public void testWontCrash()
+  {
+    final CpuSet cpuSet = new CpuSet(cgroup -> {
+      throw new RuntimeException("Should still continue");
+    });
+    final CpuSet.CpuSetMetric metric = cpuSet.snapshot();
+    Assert.assertEquals(0, metric.getCpuSetCpus().length);
+    Assert.assertEquals(0, metric.getEffectiveCpuSetCpus().length);
+    Assert.assertEquals(0, metric.getCpuSetMems().length);
+    Assert.assertEquals(0, metric.getEffectiveCpuSetMems().length);
+  }
+
+  @Test
+  public void testSimpleLoad() throws IOException
+  {
+    TestUtils.copyOrReplaceResource("/cpuset.effective_cpus.simple", new 
File(cpusetDir, "cpuset.effective_cpus"));
+    final CpuSet cpuSet = new CpuSet(discoverer);
+    final CpuSet.CpuSetMetric snapshot = cpuSet.snapshot();
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 3, 4, 5, 6, 7}, 
snapshot.getCpuSetCpus());
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 3, 4, 5, 6, 7}, 
snapshot.getEffectiveCpuSetCpus());
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 3}, snapshot.getCpuSetMems());
+    Assert.assertArrayEquals(new int[]{0}, snapshot.getEffectiveCpuSetMems());
+  }
+
+  @Test
+  public void testComplexLoad() throws IOException
+  {
+    TestUtils.copyOrReplaceResource(
+        "/cpuset.effective_cpus.complex",
+        new File(cpusetDir, "cpuset.effective_cpus")
+    );
+    final CpuSet cpuSet = new CpuSet(discoverer);
+    final CpuSet.CpuSetMetric snapshot = cpuSet.snapshot();
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 3, 4, 5, 6, 7}, 
snapshot.getCpuSetCpus());
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 7, 12, 13, 14}, 
snapshot.getEffectiveCpuSetCpus());
+    Assert.assertArrayEquals(new int[]{0, 1, 2, 3}, snapshot.getCpuSetMems());
+    Assert.assertArrayEquals(new int[]{0}, snapshot.getEffectiveCpuSetMems());
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuTest.java 
b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuTest.java
new file mode 100644
index 0000000..c2a023f
--- /dev/null
+++ b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/CpuTest.java
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.java.util.metrics.cgroups;
+
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+
+import java.io.File;
+import java.io.IOException;
+
+
+public class CpuTest
+{
+  @Rule
+  public TemporaryFolder temporaryFolder = new TemporaryFolder();
+  private CgroupDiscoverer discoverer;
+
+  @Before
+  public void setUp() throws IOException
+  {
+    File cgroupDir = temporaryFolder.newFolder();
+    File procDir = temporaryFolder.newFolder();
+    discoverer = new ProcCgroupDiscoverer(procDir.toPath());
+    TestUtils.setUpCgroups(procDir, cgroupDir);
+    final File cpuDir = new File(
+        cgroupDir,
+        
"cpu,cpuacct/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
+    );
+    Assert.assertTrue((cpuDir.isDirectory() && cpuDir.exists()) || 
cpuDir.mkdirs());
+    TestUtils.copyOrReplaceResource("/cpu.shares", new File(cpuDir, 
"cpu.shares"));
+    TestUtils.copyOrReplaceResource("/cpu.cfs_quota_us", new File(cpuDir, 
"cpu.cfs_quota_us"));
+    TestUtils.copyOrReplaceResource("/cpu.cfs_period_us", new File(cpuDir, 
"cpu.cfs_period_us"));
+  }
+
+  @Test
+  public void testWontCrash()
+  {
+    final Cpu cpu = new Cpu(cgroup -> {
+      throw new RuntimeException("Should still continue");
+    });
+    final Cpu.CpuAllocationMetric metric = cpu.snapshot();
+    Assert.assertEquals(-1L, metric.getShares());
+    Assert.assertEquals(0, metric.getQuotaUs());
+    Assert.assertEquals(0, metric.getPeriodUs());
+  }
+
+  @Test
+  public void testSimpleLoad()
+  {
+    final Cpu cpu = new Cpu(discoverer);
+    final Cpu.CpuAllocationMetric snapshot = cpu.snapshot();
+    Assert.assertEquals(1024, snapshot.getShares());
+    Assert.assertEquals(300000, snapshot.getQuotaUs());
+    Assert.assertEquals(100000, snapshot.getPeriodUs());
+  }
+}
diff --git 
a/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/TestUtils.java 
b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/TestUtils.java
index 1ba0bb1..c24b60d 100644
--- 
a/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/TestUtils.java
+++ 
b/core/src/test/java/org/apache/druid/java/util/metrics/cgroups/TestUtils.java
@@ -47,6 +47,11 @@ public class TestUtils
         cgroupDir,
         
"cpu,cpuacct/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
     ).mkdirs());
+
+    Assert.assertTrue(new File(
+        cgroupDir,
+        "cpuset/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee"
+    ).mkdirs());
     copyResource("/proc.pid.cgroup", new File(procDir, "cgroup"));
   }
 
@@ -56,4 +61,11 @@ public class TestUtils
     Assert.assertTrue(out.exists());
     Assert.assertNotEquals(0, out.length());
   }
+
+  public static void copyOrReplaceResource(String resource, File out) throws 
IOException
+  {
+    Files.copy(TestUtils.class.getResourceAsStream(resource), out.toPath());
+    Assert.assertTrue(out.exists());
+    Assert.assertNotEquals(0, out.length());
+  }
 }
diff --git a/core/src/test/resources/boot_id b/core/src/test/resources/boot_id
new file mode 100644
index 0000000..b0d4684
--- /dev/null
+++ b/core/src/test/resources/boot_id
@@ -0,0 +1 @@
+ad1f0a5c-55ea-4a49-9db8-bbb0f22e2ba6
\ No newline at end of file
diff --git a/core/src/test/resources/cpu.cfs_period_us 
b/core/src/test/resources/cpu.cfs_period_us
new file mode 100644
index 0000000..483fb82
--- /dev/null
+++ b/core/src/test/resources/cpu.cfs_period_us
@@ -0,0 +1 @@
+100000
\ No newline at end of file
diff --git a/core/src/test/resources/cpu.cfs_quota_us 
b/core/src/test/resources/cpu.cfs_quota_us
new file mode 100644
index 0000000..247d42d
--- /dev/null
+++ b/core/src/test/resources/cpu.cfs_quota_us
@@ -0,0 +1 @@
+300000
\ No newline at end of file
diff --git a/core/src/test/resources/cpu.shares 
b/core/src/test/resources/cpu.shares
new file mode 100644
index 0000000..23cbfa7
--- /dev/null
+++ b/core/src/test/resources/cpu.shares
@@ -0,0 +1 @@
+1024
\ No newline at end of file
diff --git a/core/src/test/resources/cpuinfo b/core/src/test/resources/cpuinfo
new file mode 100644
index 0000000..c8df131
--- /dev/null
+++ b/core/src/test/resources/cpuinfo
@@ -0,0 +1,223 @@
+processor      : 0
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3293.170
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 0
+cpu cores      : 4
+apicid         : 0
+initial apicid : 0
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 1
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3295.811
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 1
+cpu cores      : 4
+apicid         : 2
+initial apicid : 2
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 2
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3294.112
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 2
+cpu cores      : 4
+apicid         : 4
+initial apicid : 4
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 3
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3298.781
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 3
+cpu cores      : 4
+apicid         : 6
+initial apicid : 6
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 4
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3296.715
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 0
+cpu cores      : 4
+apicid         : 1
+initial apicid : 1
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 5
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3287.827
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 1
+cpu cores      : 4
+apicid         : 3
+initial apicid : 3
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 6
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3297.435
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 2
+cpu cores      : 4
+apicid         : 5
+initial apicid : 5
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
+
+processor      : 7
+vendor_id      : AuthenticAMD
+cpu family     : 23
+model          : 49
+model name     : AMD EPYC 7R32
+stepping       : 0
+microcode      : 0x8301034
+cpu MHz                : 3296.936
+cache size     : 512 KB
+physical id    : 0
+siblings       : 8
+core id                : 3
+cpu cores      : 4
+apicid         : 7
+initial apicid : 7
+fpu            : yes
+fpu_exception  : yes
+cpuid level    : 13
+wp             : yes
+flags          : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov 
pat pse36 clflush mmx fxsr sse sse2 ht syscall nx mmxext fxsr_opt pdpe1gb 
rdtscp lm constant_tsc rep_good nopl nonstop_tsc cpuid extd_apicid aperfmperf 
tsc_known_freq pni pclmulqdq ssse3 fma cx16 sse4_1 sse4_2 movbe popcnt aes 
xsave avx f16c rdrand hypervisor lahf_lm cmp_legacy cr8_legacy abm sse4a 
misalignsse 3dnowprefetch topoext ssbd ibrs ibpb stibp vmmcall fsgsbase bmi1 
avx2 smep bmi2 rdseed adx smap clflushopt cl [...]
+bugs           : sysret_ss_attrs spectre_v1 spectre_v2 spec_store_bypass
+bogomips       : 5600.00
+TLB size       : 3072 4K pages
+clflush size   : 64
+cache_alignment        : 64
+address sizes  : 48 bits physical, 48 bits virtual
+power management:
\ No newline at end of file
diff --git a/core/src/test/resources/cpuset.cpus 
b/core/src/test/resources/cpuset.cpus
new file mode 100644
index 0000000..2ee6e60
--- /dev/null
+++ b/core/src/test/resources/cpuset.cpus
@@ -0,0 +1 @@
+0-7
\ No newline at end of file
diff --git a/core/src/test/resources/cpuset.effective_cpus.complex 
b/core/src/test/resources/cpuset.effective_cpus.complex
new file mode 100644
index 0000000..bfc70ba
--- /dev/null
+++ b/core/src/test/resources/cpuset.effective_cpus.complex
@@ -0,0 +1 @@
+0-2,7,12-14
\ No newline at end of file
diff --git a/core/src/test/resources/cpuset.effective_cpus.simple 
b/core/src/test/resources/cpuset.effective_cpus.simple
new file mode 100644
index 0000000..2ee6e60
--- /dev/null
+++ b/core/src/test/resources/cpuset.effective_cpus.simple
@@ -0,0 +1 @@
+0-7
\ No newline at end of file
diff --git a/core/src/test/resources/cpuset.effective_mems 
b/core/src/test/resources/cpuset.effective_mems
new file mode 100644
index 0000000..c227083
--- /dev/null
+++ b/core/src/test/resources/cpuset.effective_mems
@@ -0,0 +1 @@
+0
\ No newline at end of file
diff --git a/core/src/test/resources/cpuset.mems 
b/core/src/test/resources/cpuset.mems
new file mode 100644
index 0000000..8b0ad1b
--- /dev/null
+++ b/core/src/test/resources/cpuset.mems
@@ -0,0 +1 @@
+0-3
\ No newline at end of file
diff --git a/core/src/test/resources/proc.pid.cgroup 
b/core/src/test/resources/proc.pid.cgroup
index e9ad851..179fb94 100644
--- a/core/src/test/resources/proc.pid.cgroup
+++ b/core/src/test/resources/proc.pid.cgroup
@@ -5,7 +5,7 @@
 7:devices:/system.slice/some.service
 6:freezer:/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee
 5:hugetlb:/
-4:cpuset:/
+4:cpuset:/system.slice/some.service/f12ba7e0-fa16-462e-bb9d-652ccc27f0ee
 3:memory:/system.slice/some.service
 2:net_cls,net_prio:/
 1:name=systemd:/mesos_executors.slice

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to