From 16f940716825d0a97325150d8676e23eda1d95c7 Mon Sep 17 00:00:00 2001 From: seonghun Date: Tue, 18 Aug 2026 17:17:32 +0900 Subject: [PATCH 1/3] [SCNS-1196] Apply multiprocessing to rosidl_python. --- .../rosidl_generator_py/generate_py_impl.py | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py index 16b63ece..b8f0aad1 100644 --- a/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py +++ b/rosidl_generator_py/rosidl_generator_py/generate_py_impl.py @@ -13,7 +13,10 @@ # limitations under the License. from ast import literal_eval +from concurrent.futures import ProcessPoolExecutor +from concurrent.futures import ThreadPoolExecutor import keyword +from multiprocessing import cpu_count import os import pathlib import sys @@ -53,7 +56,15 @@ } -def generate_py(generator_arguments_file, typesupport_impls): +def _parse_elements_from_idl(idl_tuple: str): + idl_parts = idl_tuple.rsplit(':', 1) + assert len(idl_parts) == 2 + locator = IdlLocator(*idl_parts) + idl_file = parse_idl_file(locator) + return idl_file.content.elements + + +def generate_py(generator_arguments_file, typesupport_impls, jobs=None): mapping = { '_idl.py.em': '_%s.py', '_idl_support.c.em': '_%s_s.c', @@ -66,7 +77,10 @@ def generate_py(generator_arguments_file, typesupport_impls): # expand init modules for each directory modules = {} idl_content = IdlContent() - for idl_tuple in args.get('idl_tuples', []): + idl_tuples = list(args.get('idl_tuples', [])) + parse_inputs = [] + + for idl_tuple in idl_tuples: idl_parts = idl_tuple.rsplit(':', 1) assert len(idl_parts) == 2 @@ -74,14 +88,40 @@ def generate_py(generator_arguments_file, typesupport_impls): idl_stems = modules.setdefault(str(idl_rel_path.parent), set()) idl_stems.add(idl_rel_path.stem) - locator = IdlLocator(*idl_parts) - idl_file = parse_idl_file(locator) - idl_content.elements += idl_file.content.elements + parse_inputs.append(idl_tuple) + + def _parse_all_with_executor(executor_cls, max_workers): + elements = [] + with executor_cls(max_workers=max_workers) as executor: + parsed_elements = executor.map( + _parse_elements_from_idl, parse_inputs, chunksize=1) + for result in parsed_elements: + elements.extend(result) + return elements + + if jobs is None or jobs <= 0: + jobs = min(cpu_count(), max(1, len(idl_tuples))) + + if parse_inputs and jobs > 1: + try: + idl_content.elements += _parse_all_with_executor( + ProcessPoolExecutor, jobs) + except Exception as e: + print( + '[rosidl_generator_py] ProcessPoolExecutor failed ' + f'({type(e).__name__}: {e}). ' + 'Falling back to ThreadPoolExecutor.', + file=sys.stderr) + idl_content.elements += _parse_all_with_executor( + ThreadPoolExecutor, jobs) + else: + for idl_tuple in parse_inputs: + idl_content.elements += _parse_elements_from_idl(idl_tuple) # NOTE(sam): remove when a language specific name mangling is implemented def print_warning_if_reserved_keyword(member_name, interface_type, interface_name): - if (keyword.iskeyword(member.name)): + if (keyword.iskeyword(member_name)): print( "Member name '{}' in the {} '{}' is a " 'reserved keyword in Python and is not supported ' From 90eec02af464d9d7228bf44c5ca08820d0e3b142 Mon Sep 17 00:00:00 2001 From: seonghun Date: Tue, 18 Aug 2026 17:17:37 +0900 Subject: [PATCH 2/3] [SCNS-1196] Apply Precompile header to rosidl_python. --- .../rosidl_generator_py_generate_interfaces.cmake | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index a6d8263e..0104b23b 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -183,6 +183,20 @@ target_include_directories(${_target_name_lib} ${PythonExtra_INCLUDE_DIRS} ) +if(ROSIDL_ENABLE_PCH AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.16") + target_precompile_headers(${_target_name_lib} PRIVATE + # _idl_pkg_typesupport_entry_point.c.em + + # _msg_pkg_typesupport_entry_point.c.em + + + [["rosidl_runtime_c/visibility_control.h"]] + [["rosidl_runtime_c/message_type_support_struct.h"]] + [["rosidl_runtime_c/service_type_support_struct.h"]] + [["rosidl_runtime_c/action_type_support_struct.h"]] + ) +endif() + # Check if numpy is in the include path find_file(_numpy_h numpy/numpyconfig.h PATHS ${PythonExtra_INCLUDE_DIRS} From d02d4ed904e1cab31bf3c92d26952f7b233f1d4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EC=84=B1=ED=9B=88=28Seonghun=20Park=29?= Date: Thu, 20 Aug 2026 11:53:49 +0900 Subject: [PATCH 3/3] Apply suggestion from @hdh7485 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: 동희(Donghee Han) Signed-off-by: 성훈(Seonghun Park) --- .../cmake/rosidl_generator_py_generate_interfaces.cmake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake index 0104b23b..f9bca10c 100644 --- a/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake +++ b/rosidl_generator_py/cmake/rosidl_generator_py_generate_interfaces.cmake @@ -183,7 +183,7 @@ target_include_directories(${_target_name_lib} ${PythonExtra_INCLUDE_DIRS} ) -if(ROSIDL_ENABLE_PCH AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.16") +if(ROSIDL_ENABLE_PCH AND COMMAND target_precompile_headers) target_precompile_headers(${_target_name_lib} PRIVATE # _idl_pkg_typesupport_entry_point.c.em