diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/ProcfsBasedProcessTree.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/ProcfsBasedProcessTree.java index 80d49c3..ab73a07 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/ProcfsBasedProcessTree.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/util/ProcfsBasedProcessTree.java @@ -56,6 +56,9 @@ .getLog(ProcfsBasedProcessTree.class); private static final String PROCFS = "/proc/"; + // To indicate mem-mapped files that are unlinked in OS + // and taken care for deletion + private static final String DELETED = "(deleted)"; private static final Pattern PROCFS_STAT_FILE_FORMAT = Pattern.compile( "^([\\d-]+)\\s\\(([^)]+)\\)\\s[^\\s]\\s([\\d-]+)\\s([\\d-]+)\\s" + @@ -99,6 +102,7 @@ public static MemInfo getMemInfoByName(String name) { private static final String KB = "kB"; private static final String READ_ONLY_WITH_SHARED_PERMISSION = "r--s"; private static final String READ_EXECUTE_WITH_SHARED_PERMISSION = "r-xs"; + private static final String READ_WRITE_PERMISSION = "rw"; private static final Pattern ADDRESS_PATTERN = Pattern .compile("([[a-f]|(0-9)]*)-([[a-f]|(0-9)]*)(\\s)*([rxwps\\-]*)"); private static final Pattern MEM_INFO_PATTERN = Pattern @@ -398,14 +402,21 @@ private long getSmapBasedRssMemorySize(int olderThanAge) { ProcessTreeSmapMemInfo procMemInfo = processSMAPTree.get(p.getPid()); if (procMemInfo != null) { for (ProcessSmapMemoryInfo info : procMemInfo.getMemoryInfoList()) { + String permission = info.getPermission().trim(); // Do not account for r--s or r-xs mappings - if (info.getPermission().trim() - .equalsIgnoreCase(READ_ONLY_WITH_SHARED_PERMISSION) - || info.getPermission().trim() - .equalsIgnoreCase(READ_EXECUTE_WITH_SHARED_PERMISSION)) { + if (permission.equalsIgnoreCase(READ_ONLY_WITH_SHARED_PERMISSION) + || permission + .equalsIgnoreCase(READ_EXECUTE_WITH_SHARED_PERMISSION)) { continue; } - + // Ignore rw* mapped files which are unlinked. + if (permission.startsWith(READ_WRITE_PERMISSION)) { + if (info.getName().endsWith(DELETED)) { + LOG.debug("Ignoring files marked for deletion " + + info.toString()); + continue; + } + } total += Math.min(info.sharedDirty, info.pss) + info.privateDirty + info.privateClean; @@ -976,6 +987,7 @@ public void setMemInfo(String key, String value) { public String toString() { StringBuilder sb = new StringBuilder(); + sb.append("\t").append(this.getPermission()).append("\n"); sb.append("\t").append(this.getName()).append("\n"); sb.append("\t").append(MemInfo.SIZE.name + ":" + this.getSize()) .append(" kB\n"); diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestProcfsBasedProcessTree.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestProcfsBasedProcessTree.java index fa4e8c8..4a04eec 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestProcfsBasedProcessTree.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/util/TestProcfsBasedProcessTree.java @@ -372,8 +372,34 @@ public void createMemoryMappingInfo(ProcessTreeSmapMemInfo[] procMemInfo) { "7f56c177c000-7f56c177d000 " + "rw-p 00010000 08:02 40371558 " + "/grid/0/jdk1.7.0_25/jre/lib/amd64/libnio.so", - new String[] { "4", "4", "25", "4", "25", "15", "10", "4", "0", "0", + // Format: size, rss, pss, shared_clean, shared_dirty, private_clean + // private_dirty, referenced, anon, anon-huge-pages, swap, + // kernel_page_size, mmu_page_size + new String[] { "4", "4", "25", "4", "25", "15", "10", "4", "0", "0", "0", "4", "4" })); + + // Following 2 mappings should not be included as it is (deleted) file + memoryMappingList.add(constructMemoryMappingInfo( + "7f56c177c000-7f56c177d000 " + + "rw-p 00010000 08:02 40371558 " + + "/grid/0/somefile (deleted)", + new String[] { "4", "1", "25", "4", "25", "0", "2096128", "4", "0", "0", + "0", "4", "4" })); + memoryMappingList.add(constructMemoryMappingInfo( + "7f56c177c000-7f56c177d000 " + + "rw-p 00010000 08:02 40371558 " + + "/dev/shm/HadoopShortCircuitShm_DFSClient_NONMAPREDUCE_" + + "-521969216_162_734673185 (deleted)", + new String[] { "4", "1", "25", "4", "25", "0", "1048064", "4", "0", "0", + "0", "4", "4" })); + + // This should be added to computation + memoryMappingList.add(constructMemoryMappingInfo( + "7f56c177c000-7f56c177d000 " + + "rw-p 00010000 08:02 40371558 " + + "somefile-521969216_162_734673185 deleted", + new String[] { "4", "1", "0", "4", "25", "0", "25", "4", "0", "0", + "0", "4", "4" })); memoryMappingList.add(constructMemoryMappingInfo( "7fb09382e000-7fb09382f000 r--s 00003000 " + "08:02 25953545", new String[] { "4", "4", "25", "4", "0", "15", "10", "4", "0", "0", @@ -474,10 +500,10 @@ public void testCpuAndMemoryForProcessTree() throws IOException { // RSS=Min(shared_dirty,PSS)+PrivateClean+PrivateDirty (exclude r-xs, // r--s) Assert.assertEquals("rss memory does not match", - (100 * KB_TO_BYTES * 3), processTree.getRssMemorySize()); + (125 * KB_TO_BYTES * 3), processTree.getRssMemorySize()); // verify old API Assert.assertEquals("rss memory (old API) does not match", - (100 * KB_TO_BYTES * 3), processTree.getCumulativeRssmem()); + (125 * KB_TO_BYTES * 3), processTree.getCumulativeRssmem()); // test the cpu time again to see if it cumulates procInfos[0] = @@ -621,10 +647,10 @@ private void testMemForOlderProcesses(boolean smapEnabled) throws IOException { cumuRssMem, processTree.getCumulativeRssmem()); } else { Assert.assertEquals("rssmem does not include new process", - 100 * KB_TO_BYTES * 4, processTree.getRssMemorySize()); + 125 * KB_TO_BYTES * 4, processTree.getRssMemorySize()); // verify old API Assert.assertEquals("rssmem (old API) does not include new process", - 100 * KB_TO_BYTES * 4, processTree.getCumulativeRssmem()); + 125 * KB_TO_BYTES * 4, processTree.getCumulativeRssmem()); } // however processes older than 1 iteration will retain the older value @@ -650,11 +676,11 @@ private void testMemForOlderProcesses(boolean smapEnabled) throws IOException { } else { Assert.assertEquals( "rssmem shouldn't have included new process", - 100 * KB_TO_BYTES * 3, processTree.getRssMemorySize(1)); + 125 * KB_TO_BYTES * 3, processTree.getRssMemorySize(1)); // Verify old API Assert.assertEquals( "rssmem (old API) shouldn't have included new process", - 100 * KB_TO_BYTES * 3, processTree.getCumulativeRssmem(1)); + 125 * KB_TO_BYTES * 3, processTree.getCumulativeRssmem(1)); } // one more process @@ -696,11 +722,11 @@ private void testMemForOlderProcesses(boolean smapEnabled) throws IOException { } else { Assert.assertEquals( "rssmem shouldn't have included new processes", - 100 * KB_TO_BYTES * 3, processTree.getRssMemorySize(2)); + 125 * KB_TO_BYTES * 3, processTree.getRssMemorySize(2)); // Verify old API Assert.assertEquals( "rssmem (old API) shouldn't have included new processes", - 100 * KB_TO_BYTES * 3, processTree.getCumulativeRssmem(2)); + 125 * KB_TO_BYTES * 3, processTree.getCumulativeRssmem(2)); } // processes older than 1 iteration should not include new process, @@ -727,10 +753,10 @@ private void testMemForOlderProcesses(boolean smapEnabled) throws IOException { } else { Assert.assertEquals( "rssmem shouldn't have included new processes", - 100 * KB_TO_BYTES * 4, processTree.getRssMemorySize(1)); + 125 * KB_TO_BYTES * 4, processTree.getRssMemorySize(1)); Assert.assertEquals( "rssmem (old API) shouldn't have included new processes", - 100 * KB_TO_BYTES * 4, processTree.getCumulativeRssmem(1)); + 125 * KB_TO_BYTES * 4, processTree.getCumulativeRssmem(1)); } // no processes older than 3 iterations