Skip to content

Commit 0639e03

Browse files
author
Matt
committed
Hand-crafted smap entry parsing
1 parent 3a207ff commit 0639e03

File tree

1 file changed

+179
-126
lines changed
  • dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/events

1 file changed

+179
-126
lines changed

dd-java-agent/agent-profiling/profiling-controller-openjdk/src/main/java/com/datadog/profiling/controller/openjdk/events/SmapEntryFactory.java

Lines changed: 179 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@
33
import datadog.trace.api.Platform;
44
import datadog.trace.bootstrap.instrumentation.jfr.JfrHelper;
55
import de.thetaphi.forbiddenapis.SuppressForbidden;
6-
import java.io.File;
6+
import java.io.BufferedReader;
77
import java.io.FileNotFoundException;
8+
import java.io.FileReader;
89
import java.lang.management.ManagementFactory;
910
import java.util.ArrayList;
1011
import java.util.Arrays;
1112
import java.util.Collections;
1213
import java.util.HashMap;
1314
import java.util.List;
14-
import java.util.Scanner;
1515
import java.util.concurrent.atomic.AtomicBoolean;
1616
import java.util.regex.Matcher;
1717
import java.util.regex.Pattern;
@@ -170,137 +170,190 @@ static List<? extends Event> collectEvents() {
170170
long locked = 0;
171171

172172
boolean thpEligible = false;
173-
String vmFlags = null;
173+
String vmFlags = "";
174174

175175
HashMap<Long, String> annotatedRegions = getAnnotatedRegions();
176-
177-
try (Scanner scanner = new Scanner(new File("/proc/self/smaps"))) {
178-
while (scanner.hasNextLine()) {
176+
try (BufferedReader reader = new BufferedReader(new FileReader("/proc/self/smaps"))) {
177+
String line;
178+
StringBuilder buffer = new StringBuilder();
179+
while ((line = reader.readLine()) != null) {
179180
boolean encounteredForeignKeys = false;
180-
String[] addresses = scanner.next().split("-");
181-
if (!addresses[0].equals(VSYSCALL_START_ADDRESS)) {
182-
startAddress = Long.parseLong(addresses[0], 16);
183-
endAddress = Long.parseLong(addresses[1], 16);
184-
} else {
185-
// vsyscall will always map to this region, but in case we ever do size calculations we
186-
// make the start
187-
// address 0x1000 less than the end address to keep relative sizing correct
188-
startAddress = -0x1000 - 1;
189-
endAddress = -1;
181+
182+
buffer.setLength(0);
183+
char[] chars = line.toCharArray();
184+
int i = 0;
185+
186+
// parse begin address
187+
while (chars[i] != '-') {
188+
buffer.append(chars[i]);
189+
i++;
190190
}
191-
perms = scanner.next();
192-
offset = scanner.nextLong(16);
193-
dev = scanner.next();
194-
inode = scanner.nextInt();
195-
if (scanner.hasNextLine()) {
196-
pathname = scanner.nextLine().trim();
197-
} else {
198-
pathname = "";
191+
startAddress = Long.decode(buffer.toString());
192+
buffer.setLength(0);
193+
i++;
194+
195+
// parse end address
196+
while (chars[i] != ' ') {
197+
buffer.append(chars[i]);
198+
i++;
199+
}
200+
endAddress = Long.decode(buffer.toString());
201+
buffer.setLength(0);
202+
i++;
203+
204+
// parse permissions
205+
while (chars[i] != ' ') {
206+
buffer.append(chars[i]);
207+
i++;
208+
}
209+
perms = buffer.toString();
210+
buffer.setLength(0);
211+
i++;
212+
213+
//
214+
// parse offset
215+
while (chars[i] != ' ') {
216+
buffer.append(chars[i]);
217+
i++;
218+
}
219+
offset = Long.decode("0x" + buffer.toString());
220+
buffer.setLength(0);
221+
i++;
222+
223+
// parse device
224+
while (chars[i] != ' ') {
225+
buffer.append(chars[i]);
226+
i++;
199227
}
228+
dev = buffer.toString();
229+
buffer.setLength(0);
230+
i++;
200231

201-
boolean reachedEnd = false;
202-
while (!reachedEnd) {
203-
String key = scanner.next();
204-
switch (key) {
205-
case "Size:":
206-
size = scanner.nextLong() * 1024;
207-
scanner.next();
208-
break;
209-
case "KernelPageSize:":
210-
kernelPageSize = scanner.nextLong() * 1024;
211-
scanner.next();
212-
break;
213-
case "MMUPageSize:":
214-
mmuPageSize = scanner.nextLong() * 1024;
215-
scanner.next();
216-
break;
217-
case "Rss:":
218-
rss = scanner.nextLong() * 1024;
219-
scanner.next();
220-
break;
221-
case "Pss:":
222-
pss = scanner.nextLong() * 1024;
223-
scanner.next();
224-
break;
225-
case "Pss_Dirty:":
226-
pssDirty = scanner.nextLong() * 1024;
227-
scanner.next();
228-
break;
229-
case "Shared_Clean:":
230-
sharedClean = scanner.nextLong() * 1024;
231-
scanner.next();
232-
break;
233-
case "Shared_Dirty:":
234-
sharedDirty = scanner.nextLong() * 1024;
235-
scanner.next();
236-
break;
237-
case "Private_Clean:":
238-
privateClean = scanner.nextLong() * 1024;
239-
scanner.next();
240-
break;
241-
case "Private_Dirty:":
242-
privateDirty = scanner.nextLong() * 1024;
243-
scanner.next();
244-
break;
245-
case "Referenced:":
246-
referenced = scanner.nextLong() * 1024;
247-
scanner.next();
248-
break;
249-
case "Anonymous:":
250-
anonymous = scanner.nextLong() * 1024;
251-
scanner.next();
252-
break;
253-
case "KSM:":
254-
ksm = scanner.nextLong() * 1024;
255-
scanner.next();
256-
break;
257-
case "LazyFree:":
258-
lazyFree = scanner.nextLong() * 1024;
259-
scanner.next();
260-
break;
261-
case "AnonHugePages:":
262-
anonHugePages = scanner.nextLong() * 1024;
263-
scanner.next();
264-
break;
265-
case "ShmemPmdMapped:":
266-
shmemPmdMapped = scanner.nextLong() * 1024;
267-
scanner.next();
268-
break;
269-
case "FilePmdMapped:":
270-
filePmdMapped = scanner.nextLong() * 1024;
271-
scanner.next();
272-
break;
273-
case "Shared_Hugetlb:":
274-
sharedHugetlb = scanner.nextLong() * 1024;
275-
scanner.next();
276-
break;
277-
case "Private_Hugetlb:":
278-
privateHugetlb = scanner.nextLong() * 1024;
279-
scanner.next();
280-
break;
281-
case "Swap:":
282-
swap = scanner.nextLong() * 1024;
283-
scanner.next();
284-
break;
285-
case "SwapPss:":
286-
swapPss = scanner.nextLong() * 1024;
287-
scanner.next();
288-
break;
289-
case "Locked:":
290-
locked = scanner.nextLong() * 1024;
291-
scanner.next();
292-
break;
293-
case "THPeligible:":
294-
thpEligible = scanner.nextInt() == 1;
295-
break;
296-
case "VmFlags:":
297-
scanner.skip("\\s+");
298-
vmFlags = scanner.nextLine();
299-
reachedEnd = true;
300-
break;
301-
default:
232+
// parse end inode
233+
while (chars[i] != ' ') {
234+
buffer.append(chars[i]);
235+
i++;
236+
}
237+
inode = Integer.decode(buffer.toString());
238+
buffer.setLength(0);
239+
i++;
240+
241+
// parse pathname
242+
while (i < chars.length) {
243+
if (chars[i] != ' ') {
244+
buffer.append(chars[i]);
245+
}
246+
i++;
247+
}
248+
pathname = buffer.toString();
249+
250+
HashMap<String, Long> attributes = new HashMap<>();
251+
while (true) {
252+
buffer.setLength(0);
253+
String attributeLine = reader.readLine();
254+
char[] attributedChars = attributeLine.toCharArray();
255+
int j = 0;
256+
while (attributedChars[j] != ':') {
257+
buffer.append(attributedChars[j]);
258+
j++;
259+
}
260+
String attributeName = buffer.toString();
261+
j++;
262+
buffer.setLength(0);
263+
264+
if (attributeName.equals("VmFlags")) {
265+
while (j < attributedChars.length) {
266+
buffer.append(attributedChars[j]);
267+
j++;
268+
}
269+
vmFlags = buffer.toString();
270+
break;
271+
} else {
272+
while (attributedChars[j] == ' ') {
273+
j++;
274+
}
275+
while (j < attributedChars.length && attributedChars[j] != ' ') {
276+
buffer.append(attributedChars[j]);
277+
j++;
278+
}
279+
if (attributeName.equals("ThpEligible")) {
280+
thpEligible = buffer.toString().equals("1");
281+
} else if (attributeName.equals("ProtectionKey")) {
282+
// Original event did not include protection key attribute, so skipping for now
302283
encounteredForeignKeys = true;
303-
break;
284+
} else {
285+
switch (attributeName) {
286+
case "Size:":
287+
size = Long.decode(buffer.toString()) * 1024;
288+
break;
289+
case "KernelPageSize:":
290+
kernelPageSize = Long.decode(buffer.toString()) * 1024;
291+
break;
292+
case "MMUPageSize:":
293+
mmuPageSize = Long.decode(buffer.toString()) * 1024;
294+
break;
295+
case "Rss:":
296+
rss = Long.decode(buffer.toString()) * 1024;
297+
break;
298+
case "Pss:":
299+
pss = Long.decode(buffer.toString()) * 1024;
300+
break;
301+
case "Pss_Dirty:":
302+
pssDirty = Long.decode(buffer.toString()) * 1024;
303+
break;
304+
case "Shared_Clean:":
305+
sharedClean = Long.decode(buffer.toString()) * 1024;
306+
break;
307+
case "Shared_Dirty:":
308+
sharedDirty = Long.decode(buffer.toString()) * 1024;
309+
break;
310+
case "Private_Clean:":
311+
privateClean = Long.decode(buffer.toString()) * 1024;
312+
break;
313+
case "Private_Dirty:":
314+
privateDirty = Long.decode(buffer.toString()) * 1024;
315+
break;
316+
case "Referenced:":
317+
referenced = Long.decode(buffer.toString()) * 1024;
318+
break;
319+
case "Anonymous:":
320+
anonymous = Long.decode(buffer.toString()) * 1024;
321+
break;
322+
case "KSM:":
323+
ksm = Long.decode(buffer.toString()) * 1024;
324+
break;
325+
case "LazyFree:":
326+
lazyFree = Long.decode(buffer.toString()) * 1024;
327+
break;
328+
case "AnonHugePages:":
329+
anonHugePages = Long.decode(buffer.toString()) * 1024;
330+
break;
331+
case "ShmemPmdMapped:":
332+
shmemPmdMapped = Long.decode(buffer.toString()) * 1024;
333+
break;
334+
case "FilePmdMapped:":
335+
filePmdMapped = Long.decode(buffer.toString()) * 1024;
336+
break;
337+
case "Shared_Hugetlb:":
338+
sharedHugetlb = Long.decode(buffer.toString()) * 1024;
339+
break;
340+
case "Private_Hugetlb:":
341+
privateHugetlb = Long.decode(buffer.toString()) * 1024;
342+
break;
343+
case "Swap:":
344+
swap = Long.decode(buffer.toString()) * 1024;
345+
break;
346+
case "SwapPss:":
347+
swapPss = Long.decode(buffer.toString()) * 1024;
348+
break;
349+
case "Locked:":
350+
locked = Long.decode(buffer.toString()) * 1024;
351+
break;
352+
default:
353+
encounteredForeignKeys = true;
354+
break;
355+
}
356+
}
304357
}
305358
}
306359

0 commit comments

Comments
 (0)