Embedding CPython in C++: Break and resume execution later? /u/knightrage Python Education

I am investigating a POC which involves embedding Python code in a C++ application (PenUltima Online, a game server). The current C++ application uses a custom, stack-based instruction set which allows running code either in a blocking (by running all the instructions) or non-blocking (by running some of the instructions, then yielding execution to other scripts) fashion. This yielding approach for non-blocking scripts allows us to have only one “script scheduler” thread that cycles between scripts ready to run, executing a number of instructions for each script.

From my understanding, any call to the CPython “run code” APIs will block the calling thread until the call finishes. This means that any code that should be non-blocking needs to run in its own thread. This would not scale well in our current paradigm: it is feasible to have several thousand non-blocking scripts,

For example, each NPC has its own non-blocking script listening for events (eg. player entered area) in order to do some action. The majority of the time, these NPC scripts are in a “waiting for event” state. A server could have several thousands worth of NPCs, and it is not feasible to have so many threads. Additionally, there’d be overhead for creating and destroying threads for all of these non-blocking scripts.

I am looking at ways to achieve the same sort of “run X instructions” approach in Python so I could have only one script scheduler thread. I’ve been looking around the GIL, subinterpreters, frame evaluation, etc., but I don’t see how any of these things can help me.

What I found is that _PyEval_EvalFrameDefault is the main entry point for evaluating Python code, with a handler for each opcode instruction. Is there a way to exit out of this function and resume execution later? I don’t think this is supported with the default frame evaluator, but perhaps there is a way to do this with a custom one (that could be set via _PyInterpreterState_SetEvalFrameFunc)?

Or is there any way, in general, to context switch between Python code evaluation within a single std::thread? Maybe there is a different Python engine (other than CPython) that can be embedded in C++ which has this feature?

submitted by /u/knightrage
[link] [comments]

​r/learnpython I am investigating a POC which involves embedding Python code in a C++ application (PenUltima Online, a game server). The current C++ application uses a custom, stack-based instruction set which allows running code either in a blocking (by running all the instructions) or non-blocking (by running some of the instructions, then yielding execution to other scripts) fashion. This yielding approach for non-blocking scripts allows us to have only one “script scheduler” thread that cycles between scripts ready to run, executing a number of instructions for each script. From my understanding, any call to the CPython “run code” APIs will block the calling thread until the call finishes. This means that any code that should be non-blocking needs to run in its own thread. This would not scale well in our current paradigm: it is feasible to have several thousand non-blocking scripts, For example, each NPC has its own non-blocking script listening for events (eg. player entered area) in order to do some action. The majority of the time, these NPC scripts are in a “waiting for event” state. A server could have several thousands worth of NPCs, and it is not feasible to have so many threads. Additionally, there’d be overhead for creating and destroying threads for all of these non-blocking scripts. I am looking at ways to achieve the same sort of “run X instructions” approach in Python so I could have only one script scheduler thread. I’ve been looking around the GIL, subinterpreters, frame evaluation, etc., but I don’t see how any of these things can help me. What I found is that _PyEval_EvalFrameDefault is the main entry point for evaluating Python code, with a handler for each opcode instruction. Is there a way to exit out of this function and resume execution later? I don’t think this is supported with the default frame evaluator, but perhaps there is a way to do this with a custom one (that could be set via _PyInterpreterState_SetEvalFrameFunc)? Or is there any way, in general, to context switch between Python code evaluation within a single std::thread? Maybe there is a different Python engine (other than CPython) that can be embedded in C++ which has this feature? submitted by /u/knightrage [link] [comments] 

I am investigating a POC which involves embedding Python code in a C++ application (PenUltima Online, a game server). The current C++ application uses a custom, stack-based instruction set which allows running code either in a blocking (by running all the instructions) or non-blocking (by running some of the instructions, then yielding execution to other scripts) fashion. This yielding approach for non-blocking scripts allows us to have only one “script scheduler” thread that cycles between scripts ready to run, executing a number of instructions for each script.

From my understanding, any call to the CPython “run code” APIs will block the calling thread until the call finishes. This means that any code that should be non-blocking needs to run in its own thread. This would not scale well in our current paradigm: it is feasible to have several thousand non-blocking scripts,

For example, each NPC has its own non-blocking script listening for events (eg. player entered area) in order to do some action. The majority of the time, these NPC scripts are in a “waiting for event” state. A server could have several thousands worth of NPCs, and it is not feasible to have so many threads. Additionally, there’d be overhead for creating and destroying threads for all of these non-blocking scripts.

I am looking at ways to achieve the same sort of “run X instructions” approach in Python so I could have only one script scheduler thread. I’ve been looking around the GIL, subinterpreters, frame evaluation, etc., but I don’t see how any of these things can help me.

What I found is that _PyEval_EvalFrameDefault is the main entry point for evaluating Python code, with a handler for each opcode instruction. Is there a way to exit out of this function and resume execution later? I don’t think this is supported with the default frame evaluator, but perhaps there is a way to do this with a custom one (that could be set via _PyInterpreterState_SetEvalFrameFunc)?

Or is there any way, in general, to context switch between Python code evaluation within a single std::thread? Maybe there is a different Python engine (other than CPython) that can be embedded in C++ which has this feature?

submitted by /u/knightrage
[link] [comments] 

Leave a Reply

Your email address will not be published. Required fields are marked *