Skip to content

Commit b0e4eba

Browse files
committed
[GR-38964] Convert system property HPyTraceUpcalls to polyglot option.
PullRequest: graalpython/2289
2 parents 8e333e9 + 4b8e549 commit b0e4eba

File tree

2 files changed

+65
-95
lines changed

2 files changed

+65
-95
lines changed

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/objects/cext/hpy/GraalHPyContext.java

Lines changed: 61 additions & 95 deletions
Original file line numberDiff line numberDiff line change
@@ -270,27 +270,7 @@
270270
@ExportLibrary(value = NativeTypeLibrary.class, useForAOT = false)
271271
public class GraalHPyContext extends CExtContext implements TruffleObject {
272272

273-
private static final boolean TRACE;
274-
private static final int TRACE_SLEEP_TIME;
275-
static {
276-
String prop = System.getProperty("HPyTraceUpcalls");
277-
boolean doTrace = false;
278-
int sleepTime = 5000;
279-
if (prop != null) {
280-
if (prop.equals("true")) {
281-
doTrace = true;
282-
} else {
283-
try {
284-
sleepTime = Integer.parseInt(prop);
285-
doTrace = true;
286-
} catch (NumberFormatException e) {
287-
// pass
288-
}
289-
}
290-
}
291-
TRACE = doTrace;
292-
TRACE_SLEEP_TIME = sleepTime;
293-
}
273+
private final boolean traceJNIUpcalls;
294274

295275
private static final TruffleLogger LOGGER = PythonLanguage.getLogger(GraalHPyContext.class);
296276

@@ -857,8 +837,12 @@ public static GraalHPyNativeSymbol getGetterFunctionName(LLVMType llvmType) {
857837

858838
public GraalHPyContext(PythonContext context, Object hpyLibrary) {
859839
super(context, hpyLibrary, GraalHPyConversionNodeSupplier.HANDLE);
840+
PythonLanguage language = context.getLanguage();
841+
useNativeFastPaths = language.getEngineOption(PythonOptions.HPyEnableJNIFastPaths);
842+
int traceJNISleepTime = language.getEngineOption(PythonOptions.HPyTraceUpcalls);
843+
traceJNIUpcalls = traceJNISleepTime != 0;
860844
this.slowPathFactory = context.factory();
861-
this.hpyContextMembers = createMembers(context, getName());
845+
this.hpyContextMembers = createMembers(context, getName(), traceJNIUpcalls);
862846
for (Object member : hpyContextMembers) {
863847
if (member instanceof GraalHPyHandle) {
864848
GraalHPyHandle handle = (GraalHPyHandle) member;
@@ -869,7 +853,9 @@ public GraalHPyContext(PythonContext context, Object hpyLibrary) {
869853
}
870854
hpyHandleTable = Arrays.copyOf(hpyHandleTable, IMMUTABLE_HANDLE_COUNT * 2);
871855
nextHandle = IMMUTABLE_HANDLE_COUNT;
872-
this.useNativeFastPaths = context.getLanguage().getEngineOption(PythonOptions.HPyEnableJNIFastPaths);
856+
if (traceJNIUpcalls) {
857+
startUpcallsDaemon(traceJNISleepTime);
858+
}
873859
}
874860

875861
protected String getName() {
@@ -1394,45 +1380,23 @@ public enum Counter {
13941380
UpcallListNew,
13951381
UpcallTupleFromArray;
13961382

1397-
long count;
1398-
1399-
void increment() {
1400-
if (TRACE) {
1401-
count++;
1402-
}
1403-
}
1383+
@CompilationFinal(dimensions = 1) private static final Counter[] VALUES = values();
14041384
}
14051385

1406-
static {
1407-
if (TRACE) {
1408-
Thread thread = new Thread(() -> {
1409-
1410-
while (true) {
1411-
try {
1412-
Thread.sleep(TRACE_SLEEP_TIME);
1413-
} catch (InterruptedException e) {
1414-
// fall through
1415-
}
1416-
System.out.println("==== HPy counts");
1417-
for (Counter c : Counter.values()) {
1418-
System.out.printf(" %20s: %8d\n", c.name(), c.count);
1419-
}
1420-
}
1421-
1422-
});
1423-
thread.setDaemon(true);
1424-
thread.start();
1386+
private void increment(Counter upcall) {
1387+
if (traceJNIUpcalls) {
1388+
jniCounts[upcall.ordinal()]++;
14251389
}
14261390
}
14271391

14281392
@SuppressWarnings("static-method")
14291393
public final long ctxFloatFromDouble(double value) {
1430-
Counter.UpcallFloatFromDouble.increment();
1394+
increment(Counter.UpcallFloatFromDouble);
14311395
return GraalHPyBoxing.boxDouble(value);
14321396
}
14331397

14341398
public final double ctxFloatAsDouble(long handle) {
1435-
Counter.UpcallFloatAsDouble.increment();
1399+
increment(Counter.UpcallFloatAsDouble);
14361400

14371401
if (GraalHPyBoxing.isBoxedDouble(handle)) {
14381402
return GraalHPyBoxing.unboxDouble(handle);
@@ -1446,7 +1410,7 @@ public final double ctxFloatAsDouble(long handle) {
14461410
}
14471411

14481412
public final long ctxLongAsLong(long handle) {
1449-
Counter.UpcallLongAsLong.increment();
1413+
increment(Counter.UpcallLongAsLong);
14501414

14511415
if (GraalHPyBoxing.isBoxedInt(handle)) {
14521416
return GraalHPyBoxing.unboxInt(handle);
@@ -1462,7 +1426,7 @@ public final long ctxLongAsLong(long handle) {
14621426
}
14631427

14641428
public final double ctxLongAsDouble(long handle) {
1465-
Counter.UpcallLongAsDouble.increment();
1429+
increment(Counter.UpcallLongAsDouble);
14661430

14671431
if (GraalHPyBoxing.isBoxedInt(handle)) {
14681432
return GraalHPyBoxing.unboxInt(handle);
@@ -1478,7 +1442,7 @@ public final double ctxLongAsDouble(long handle) {
14781442
}
14791443

14801444
public final long ctxLongFromLong(long l) {
1481-
Counter.UpcallLongFromLong.increment();
1445+
increment(Counter.UpcallLongFromLong);
14821446

14831447
if (com.oracle.graal.python.builtins.objects.ints.PInt.isIntRange(l)) {
14841448
return GraalHPyBoxing.boxInt((int) l);
@@ -1487,14 +1451,14 @@ public final long ctxLongFromLong(long l) {
14871451
}
14881452

14891453
public final long ctxAsStruct(long handle) {
1490-
Counter.UpcallCast.increment();
1454+
increment(Counter.UpcallCast);
14911455

14921456
Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate();
14931457
return (long) HPyGetNativeSpacePointerNodeGen.getUncached().execute(receiver);
14941458
}
14951459

14961460
public final long ctxNew(long typeHandle, long dataOutVar) {
1497-
Counter.UpcallNew.increment();
1461+
increment(Counter.UpcallNew);
14981462

14991463
Object type = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(typeHandle)).getDelegate();
15001464
PythonObject pythonObject;
@@ -1536,7 +1500,7 @@ public final long ctxNew(long typeHandle, long dataOutVar) {
15361500
}
15371501

15381502
public final long ctxTypeGenericNew(long typeHandle) {
1539-
Counter.UpcallTypeGenericNew.increment();
1503+
increment(Counter.UpcallTypeGenericNew);
15401504

15411505
Object type = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(typeHandle)).getDelegate();
15421506

@@ -1568,12 +1532,12 @@ private void closeNativeHandle(long handle) {
15681532
}
15691533

15701534
public final void ctxClose(long handle) {
1571-
Counter.UpcallClose.increment();
1535+
increment(Counter.UpcallClose);
15721536
closeNativeHandle(handle);
15731537
}
15741538

15751539
public final void ctxBulkClose(long unclosedHandlePtr, int size) {
1576-
Counter.UpcallBulkClose.increment();
1540+
increment(Counter.UpcallBulkClose);
15771541
for (int i = 0; i < size; i++) {
15781542
long handle = unsafe.getLong(unclosedHandlePtr);
15791543
unclosedHandlePtr += 8;
@@ -1584,7 +1548,7 @@ public final void ctxBulkClose(long unclosedHandlePtr, int size) {
15841548
}
15851549

15861550
public final long ctxDup(long handle) {
1587-
Counter.UpcallDup.increment();
1551+
increment(Counter.UpcallDup);
15881552
if (GraalHPyBoxing.isBoxedHandle(handle)) {
15891553
GraalHPyHandle pyHandle = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle));
15901554
return GraalHPyBoxing.boxHandle(createHandle(pyHandle.getDelegate()).getId(this, ConditionProfile.getUncached()));
@@ -1594,7 +1558,7 @@ public final long ctxDup(long handle) {
15941558
}
15951559

15961560
public final long ctxGetItemi(long hCollection, long lidx) {
1597-
Counter.UpcallGetItemI.increment();
1561+
increment(Counter.UpcallGetItemI);
15981562
try {
15991563
// If handle 'hCollection' is a boxed int or double, the object is not subscriptable.
16001564
if (!GraalHPyBoxing.isBoxedHandle(hCollection)) {
@@ -1648,7 +1612,7 @@ public final long ctxGetItemi(long hCollection, long lidx) {
16481612
* @return {@code 0} on success; {@code -1} on error
16491613
*/
16501614
public final int ctxSetItem(long hSequence, long hKey, long hValue) {
1651-
Counter.UpcallSetItem.increment();
1615+
increment(Counter.UpcallSetItem);
16521616
try {
16531617
// If handle 'hSequence' is a boxed int or double, the object is not a sequence.
16541618
if (!GraalHPyBoxing.isBoxedHandle(hSequence)) {
@@ -1691,7 +1655,7 @@ public final int ctxSetItem(long hSequence, long hKey, long hValue) {
16911655
}
16921656

16931657
public final int ctxSetItemi(long hSequence, long lidx, long hValue) {
1694-
Counter.UpcallSetItemI.increment();
1658+
increment(Counter.UpcallSetItemI);
16951659
try {
16961660
// If handle 'hSequence' is a boxed int or double, the object is not a sequence.
16971661
if (!GraalHPyBoxing.isBoxedHandle(hSequence)) {
@@ -1748,7 +1712,7 @@ private static int setItemGeneric(Object receiver, Object clazz, Object key, Obj
17481712
}
17491713

17501714
public final int ctxNumberCheck(long handle) {
1751-
Counter.UpcallNumberCheck.increment();
1715+
increment(Counter.UpcallNumberCheck);
17521716
if (GraalHPyBoxing.isBoxedDouble(handle) || GraalHPyBoxing.isBoxedInt(handle)) {
17531717
return 1;
17541718
}
@@ -1777,7 +1741,7 @@ private static PythonBuiltinClassType getBuiltinClass(Object cls) {
17771741
}
17781742

17791743
public final int ctxTypeCheck(long handle, long typeHandle) {
1780-
Counter.UpcallTypeCheck.increment();
1744+
increment(Counter.UpcallTypeCheck);
17811745
Object receiver;
17821746
if (GraalHPyBoxing.isBoxedDouble(handle)) {
17831747
receiver = PythonBuiltinClassType.PFloat;
@@ -1820,7 +1784,7 @@ public final int ctxTypeCheck(long handle, long typeHandle) {
18201784
}
18211785

18221786
public final long ctxLength(long handle) {
1823-
Counter.UpcallLength.increment();
1787+
increment(Counter.UpcallLength);
18241788
assert GraalHPyBoxing.isBoxedHandle(handle);
18251789

18261790
Object receiver = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate();
@@ -1840,7 +1804,7 @@ public final long ctxLength(long handle) {
18401804
}
18411805

18421806
public final int ctxListCheck(long handle) {
1843-
Counter.UpcallListCheck.increment();
1807+
increment(Counter.UpcallListCheck);
18441808
if (GraalHPyBoxing.isBoxedHandle(handle)) {
18451809
Object obj = getObjectForHPyHandle(GraalHPyBoxing.unboxHandle(handle)).getDelegate();
18461810
Object clazz = GetClassNode.getUncached().execute(obj);
@@ -1851,7 +1815,7 @@ public final int ctxListCheck(long handle) {
18511815
}
18521816

18531817
public final long ctxUnicodeFromWideChar(long wcharArrayPtr, long size) {
1854-
Counter.UpcallUnicodeFromWideChar.increment();
1818+
increment(Counter.UpcallUnicodeFromWideChar);
18551819

18561820
if (!PInt.isIntRange(size)) {
18571821
// NULL handle
@@ -1873,19 +1837,19 @@ public final long ctxUnicodeFromWideChar(long wcharArrayPtr, long size) {
18731837
}
18741838

18751839
public final long ctxUnicodeFromJCharArray(char[] arr) {
1876-
Counter.UpcallUnicodeFromJCharArray.increment();
1840+
increment(Counter.UpcallUnicodeFromJCharArray);
18771841
return createHandle(new String(arr, 0, arr.length)).getId(this, ConditionProfile.getUncached());
18781842
}
18791843

18801844
public final long ctxDictNew() {
1881-
Counter.UpcallDictNew.increment();
1845+
increment(Counter.UpcallDictNew);
18821846
PDict dict = PythonObjectFactory.getUncached().createDict();
18831847
return createHandle(dict).getId(this, ConditionProfile.getUncached());
18841848
}
18851849

18861850
public final long ctxListNew(long llen) {
18871851
try {
1888-
Counter.UpcallListNew.increment();
1852+
increment(Counter.UpcallListNew);
18891853
int len = CastToJavaIntExactNode.getUncached().execute(llen);
18901854
Object[] data = new Object[len];
18911855
Arrays.fill(data, PNone.NONE);
@@ -1904,7 +1868,7 @@ public final long ctxListNew(long llen) {
19041868
* is useful to implement, e.g., tuple builder.
19051869
*/
19061870
public final long ctxTupleFromArray(long[] hItems, boolean steal) {
1907-
Counter.UpcallTupleFromArray.increment();
1871+
increment(Counter.UpcallTupleFromArray);
19081872

19091873
Object[] objects = new Object[hItems.length];
19101874
for (int i = 0; i < hItems.length; i++) {
@@ -2014,7 +1978,7 @@ final Object invokeMember(String key, Object[] args,
20141978
return memberInvokeLib.execute(member, args);
20151979
}
20161980

2017-
private static Object[] createMembers(PythonContext context, String name) {
1981+
private static Object[] createMembers(PythonContext context, String name, boolean traceJNIUpcalls) {
20181982
Object[] members = new Object[HPyContextMember.VALUES.length];
20191983

20201984
members[HPyContextMember.NAME.ordinal()] = new CStringWrapper(name);
@@ -2276,7 +2240,7 @@ private static Object[] createMembers(PythonContext context, String name) {
22762240
members[HPyContextMember.CTX_GLOBAL_LOAD.ordinal()] = new GraalHPyGlobalLoad();
22772241
members[HPyContextMember.CTX_DUMP.ordinal()] = new GraalHPyDump();
22782242

2279-
if (TRACE) {
2243+
if (traceJNIUpcalls) {
22802244
for (int i = 0; i < members.length; i++) {
22812245
Object m = members[i];
22822246
if (m != null && !(m instanceof Number || m instanceof GraalHPyHandle)) {
@@ -2290,30 +2254,32 @@ private static Object[] createMembers(PythonContext context, String name) {
22902254
}
22912255

22922256
static final int[] counts = new int[HPyContextMember.VALUES.length];
2257+
static final int[] jniCounts = new int[Counter.values().length];
22932258

2294-
static {
2295-
if (TRACE) {
2296-
Thread thread = new Thread() {
2297-
@Override
2298-
public void run() {
2299-
while (true) {
2300-
try {
2301-
Thread.sleep(TRACE_SLEEP_TIME);
2302-
} catch (InterruptedException e) {
2303-
e.printStackTrace();
2304-
}
2305-
System.out.println("========= stats");
2306-
for (int i = 0; i < counts.length; i++) {
2307-
if (counts[i] != 0) {
2308-
System.out.printf(" %40s[%3d]: %d\n", HPyContextMember.VALUES[i].name, i, counts[i]);
2309-
}
2310-
}
2259+
private static void startUpcallsDaemon(int traceJNISleepTime) {
2260+
Thread thread = new Thread(() -> {
2261+
while (true) {
2262+
try {
2263+
Thread.sleep(traceJNISleepTime);
2264+
} catch (InterruptedException e) {
2265+
e.printStackTrace();
2266+
}
2267+
System.out.println("========= HPy LLVM/NFI upcall counts");
2268+
for (int i = 0; i < counts.length; i++) {
2269+
if (counts[i] != 0) {
2270+
System.out.printf(" %40s[%3d]: %d\n", HPyContextMember.VALUES[i].name, i, counts[i]);
23112271
}
23122272
}
2313-
};
2314-
thread.setDaemon(true);
2315-
thread.start();
2316-
}
2273+
System.out.println("==== HPy JNI upcall counts");
2274+
for (int i = 0; i < jniCounts.length; i++) {
2275+
if (jniCounts[i] != 0) {
2276+
System.out.printf(" %40s[%3d]: %d\n", Counter.VALUES[i].name(), i, jniCounts[i]);
2277+
}
2278+
}
2279+
}
2280+
});
2281+
thread.setDaemon(true);
2282+
thread.start();
23172283
}
23182284

23192285
@ExportLibrary(value = InteropLibrary.class, delegateTo = "delegate")

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PythonOptions.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,10 @@ private PythonOptions() {
189189
"when HPy API functions are used. This is achieved by mirroring data in native memory.", stability = OptionStability.EXPERIMENTAL) //
190190
public static final OptionKey<Boolean> HPyEnableJNIFastPaths = new OptionKey<>(true);
191191

192+
@EngineOption @Option(category = OptionCategory.INTERNAL, usageSyntax = "<time>", help = "Specifies the interval (ms) for periodically printing HPy upcall statistics. If {@code 0}" +
193+
"or not specified, nothing will be printed (default).", stability = OptionStability.EXPERIMENTAL) //
194+
public static final OptionKey<Integer> HPyTraceUpcalls = new OptionKey<>(0);
195+
192196
@Option(category = OptionCategory.INTERNAL, usageSyntax = "<path>", help = "Specify the directory where the JNI library is located.", stability = OptionStability.EXPERIMENTAL) //
193197
public static final OptionKey<String> JNIHome = new OptionKey<>("");
194198

0 commit comments

Comments
 (0)