Skip to content

Commit b285559

Browse files
committed
[GR-58473][GR-58526][GR-58707] Async GC with RSS guidance
PullRequest: graalpython/3499
2 parents 5560c3c + 0f2639e commit b285559

File tree

14 files changed

+331
-38
lines changed

14 files changed

+331
-38
lines changed

graalpython/com.oracle.graal.python.cext/include/Python.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1+
/* Copyright (c) 2022, 2024, Oracle and/or its affiliates.
22
* Copyright (C) 1996-2022 Python Software Foundation
33
*
44
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
@@ -64,6 +64,7 @@ struct timeval;
6464
#include "boolobject.h"
6565
#include "floatobject.h"
6666
#include "complexobject.h"
67+
#include "rangeobject.h"
6768
#include "memoryobject.h"
6869
#include "tupleobject.h"
6970
#include "listobject.h"
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/* Copyright (c) 2018, 2024, Oracle and/or its affiliates.
2+
* Copyright (C) 1996-2020 Python Software Foundation
3+
*
4+
* Licensed under the PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2
5+
*/
6+
7+
/* Range object interface */
8+
9+
#ifndef Py_RANGEOBJECT_H
10+
#define Py_RANGEOBJECT_H
11+
#ifdef __cplusplus
12+
extern "C" {
13+
#endif
14+
15+
/*
16+
A range object represents an integer range. This is an immutable object;
17+
a range cannot change its value after creation.
18+
19+
Range objects behave like the corresponding tuple objects except that
20+
they are represented by a start, stop, and step datamembers.
21+
*/
22+
23+
PyAPI_DATA(PyTypeObject) PyRange_Type;
24+
PyAPI_DATA(PyTypeObject) PyRangeIter_Type;
25+
PyAPI_DATA(PyTypeObject) PyLongRangeIter_Type;
26+
27+
#define PyRange_Check(op) Py_IS_TYPE(op, &PyRange_Type)
28+
29+
#ifdef __cplusplus
30+
}
31+
#endif
32+
#endif /* !Py_RANGEOBJECT_H */

graalpython/com.oracle.graal.python.cext/src/capi.c

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -566,6 +566,44 @@ PyAPI_FUNC(void) PyTruffle_ObjectArrayRelease(PyObject** array, int32_t size) {
566566
}
567567
}
568568

569+
#if defined(__APPLE__) && defined(__MACH__)
570+
#include <mach/mach.h>
571+
#elif defined(_WIN32)
572+
#include <windows.h>
573+
#include "psapi.h"
574+
#endif
575+
576+
PyAPI_FUNC(size_t) PyTruffle_GetCurrentRSS() {
577+
size_t rss = 0;
578+
#if defined(__APPLE__) && defined(__MACH__)
579+
// MacOS
580+
struct mach_task_basic_info info;
581+
mach_msg_type_number_t infoCount = MACH_TASK_BASIC_INFO_COUNT;
582+
if (task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t) &info, &infoCount) == KERN_SUCCESS) {
583+
rss = (size_t)info.resident_size;
584+
}
585+
586+
#elif defined(__linux__) || defined(__gnu_linux__)
587+
// Linux
588+
FILE* fp = NULL;
589+
if ((fp = fopen( "/proc/self/statm", "r" )) != NULL) {
590+
if (fscanf(fp, "%*s%ld", (long) &rss)) {
591+
rss *= (uint64_t) sysconf( _SC_PAGESIZE);
592+
}
593+
fclose(fp);
594+
}
595+
596+
#elif defined(_WIN32)
597+
// Windows
598+
PROCESS_MEMORY_COUNTERS pmc;
599+
if (GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) {
600+
rss = pmc.WorkingSetSize;
601+
}
602+
#endif
603+
return rss / (1024 * 1024 /* bytes -> megabytes*/);
604+
}
605+
606+
569607
#define ReadMember(object, offset, T) ((T*)(((char*)object) + offset))[0]
570608

571609
PyAPI_FUNC(int) ReadShortMember(void* object, Py_ssize_t offset) {

graalpython/com.oracle.graal.python.cext/src/tupleobject.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1418,5 +1418,9 @@ PyTruffleTuple_GetItems(PyObject *op)
14181418
*/
14191419
PyObject*
14201420
_PyTuple_GET_ITEM(PyObject* a, Py_ssize_t b) {
1421-
return PyTruffleTuple_GetItems(a)[b];
1421+
PyObject **ob_item = PyTruffleTuple_GetItems(a);
1422+
if (ob_item) {
1423+
return ob_item[b];
1424+
}
1425+
return NULL; // an exception has happend during transtion
14221426
}

graalpython/com.oracle.graal.python.test/src/tests/cpyext/test_gc.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -896,3 +896,7 @@ def test_module_globals(self):
896896
####################################### GC #######################################
897897
self._trigger_gc()
898898
##################################################################################
899+
900+
@skipIf(not (GRAALPY) or RUNS_ON_LLVM, "Internal GraalPy RSS function")
901+
def test_current_rss_monitor():
902+
assert __graalpython__.get_current_rss() > 0

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GcModuleBuiltins.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@
5757
import com.oracle.graal.python.nodes.call.special.CallBinaryMethodNode;
5858
import com.oracle.graal.python.nodes.function.PythonBuiltinBaseNode;
5959
import com.oracle.graal.python.nodes.function.PythonBuiltinNode;
60-
import com.oracle.graal.python.nodes.function.builtins.PythonClinicBuiltinNode;
60+
import com.oracle.graal.python.nodes.function.builtins.PythonBinaryClinicBuiltinNode;
6161
import com.oracle.graal.python.nodes.function.builtins.PythonUnaryClinicBuiltinNode;
6262
import com.oracle.graal.python.nodes.function.builtins.clinic.ArgumentClinicProvider;
6363
import com.oracle.graal.python.runtime.GilNode;
@@ -112,7 +112,7 @@ public void initialize(Python3Core core) {
112112
@Builtin(name = "collect", parameterNames = {"$self", "generation"}, declaresExplicitSelf = true)
113113
@ArgumentClinic(name = "generation", conversion = ClinicConversion.Int, defaultValue = "2")
114114
@GenerateNodeFactory
115-
abstract static class GcCollectNode extends PythonClinicBuiltinNode {
115+
abstract static class GcCollectNode extends PythonBinaryClinicBuiltinNode {
116116
private static final NativeCAPISymbol SYMBOL = NativeCAPISymbol.FUN_GRAALPY_GC_COLLECT;
117117
private static final CApiTiming C_API_TIMING = CApiTiming.create(true, SYMBOL.getName());
118118

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/GraalPythonModuleBuiltins.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,6 @@
7878
import java.util.List;
7979
import java.util.logging.Level;
8080

81-
import com.oracle.graal.python.nodes.util.ToNativePrimitiveStorageNode;
82-
import com.oracle.graal.python.runtime.sequence.storage.NativePrimitiveSequenceStorage;
8381
import org.graalvm.home.Version;
8482
import org.graalvm.nativeimage.ImageInfo;
8583

@@ -148,6 +146,7 @@
148146
import com.oracle.graal.python.nodes.statement.AbstractImportNode;
149147
import com.oracle.graal.python.nodes.truffle.PythonArithmeticTypes;
150148
import com.oracle.graal.python.nodes.util.CastToTruffleStringNode;
149+
import com.oracle.graal.python.nodes.util.ToNativePrimitiveStorageNode;
151150
import com.oracle.graal.python.runtime.PosixSupportLibrary;
152151
import com.oracle.graal.python.runtime.PythonContext;
153152
import com.oracle.graal.python.runtime.PythonImageBuildOptions;
@@ -156,6 +155,7 @@
156155
import com.oracle.graal.python.runtime.exception.PythonExitException;
157156
import com.oracle.graal.python.runtime.object.PythonObjectFactory;
158157
import com.oracle.graal.python.runtime.sequence.PSequence;
158+
import com.oracle.graal.python.runtime.sequence.storage.NativePrimitiveSequenceStorage;
159159
import com.oracle.graal.python.runtime.sequence.storage.NativeSequenceStorage;
160160
import com.oracle.graal.python.runtime.sequence.storage.SequenceStorage;
161161
import com.oracle.graal.python.util.PythonUtils;
@@ -1131,4 +1131,15 @@ Object doClear() {
11311131
return PNone.NONE;
11321132
}
11331133
}
1134+
1135+
@Builtin(name = "get_current_rss", maxNumOfPositionalArgs = 0)
1136+
@GenerateNodeFactory
1137+
public abstract static class GetCurrentRSS extends PythonBuiltinNode {
1138+
1139+
@Specialization
1140+
@TruffleBoundary
1141+
Object currentRSS() {
1142+
return getContext().getCApiContext().getCurrentRSS();
1143+
}
1144+
}
11341145
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/cext/PythonCextWeakrefBuiltins.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,8 +79,14 @@ static Object refType(Object object, Object callback,
7979
@CApiBuiltin(ret = PyObjectBorrowed, args = {PyObject}, call = Direct)
8080
abstract static class PyWeakref_GetObject extends CApiUnaryBuiltinNode {
8181
@Specialization
82-
static Object call(PReferenceType self) {
83-
return self.getPyObject();
82+
static Object call(Object reference) {
83+
if (reference instanceof PReferenceType ref) {
84+
return ref.getPyObject();
85+
}
86+
/*
87+
* This weak reference has died in the managed side due to its referent being collected.
88+
*/
89+
return PNone.NONE;
8490
}
8591
}
8692
}

0 commit comments

Comments
 (0)