From 86ac5eb39054bac469e7f8beb59a5e210c028dd6 Mon Sep 17 00:00:00 2001 From: "codeflash-ai[bot]" <148906541+codeflash-ai[bot]@users.noreply.github.com> Date: Thu, 18 Dec 2025 14:09:43 +0000 Subject: [PATCH] Optimize OneNoteDataSource.groups_onenote_sections_pages_get_parent_notebook The optimization achieves a **26% runtime improvement** by implementing **lazy instantiation** of Microsoft Graph SDK objects, avoiding unnecessary object creation when optional parameters are not provided. **Key optimizations applied:** 1. **Conditional object instantiation**: Instead of always creating `SectionsRequestBuilderGetQueryParameters()` and `SectionsRequestBuilderGetRequestConfiguration()` objects, they are only created when needed. The code checks if any query parameters are actually provided before instantiation. 2. **Early exit pattern**: The optimization uses `query_params = None` and `config = None` as starting points, then conditionally creates these objects only when `select`, `expand`, `filter`, `orderby`, `search`, `top`, `skip`, or `headers` are provided. **Why this leads to speedup:** - **Object creation overhead**: The line profiler shows the original code spent 16.5% of time (390,751ns) just creating the query parameters object, and 8.8% (207,838ns) creating the configuration object on every call - **Reduced memory allocation**: In the optimized version, when no parameters are provided (the common case), these expensive object creations are completely avoided - **CPU cache efficiency**: Less object instantiation means better cache locality and reduced garbage collection pressure **Performance analysis from profiler data:** - Original: 2,369,540ns total time with heavy object creation costs - Optimized: 1,553,450ns total time with conditional object creation - The Microsoft Graph API call itself (48.9% vs 34.1% of total time) shows the optimization successfully reduces overhead around the actual network call **Test case performance:** The optimization is particularly effective for the common scenario where methods are called with minimal parameters. Most test cases show consistent improvements, especially the basic success cases and concurrent execution tests that represent typical usage patterns. While throughput remains the same at 915 operations/second due to the async nature being I/O bound, the reduced CPU overhead per operation makes this optimization valuable for applications with high OneNote API call frequency. --- .../external/microsoft/one_note/one_note.py | 61 ++++++++++--------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/backend/python/app/sources/external/microsoft/one_note/one_note.py b/backend/python/app/sources/external/microsoft/one_note/one_note.py index 76dbc9ad19..fb2fcab137 100644 --- a/backend/python/app/sources/external/microsoft/one_note/one_note.py +++ b/backend/python/app/sources/external/microsoft/one_note/one_note.py @@ -1,5 +1,3 @@ - - import json import logging from dataclasses import asdict @@ -5407,36 +5405,41 @@ async def groups_onenote_sections_pages_get_parent_notebook( """ # Build query parameters including OData for OneNote try: - # Use typed query parameters - query_params = SectionsRequestBuilder.SectionsRequestBuilderGetQueryParameters() - # Set query parameters using typed object properties - if select: - query_params.select = select if isinstance(select, list) else [select] - if expand: - query_params.expand = expand if isinstance(expand, list) else [expand] - if filter: - query_params.filter = filter - if orderby: - query_params.orderby = orderby - if search: - query_params.search = search - if top is not None: - query_params.top = top - if skip is not None: - query_params.skip = skip + # Only create query parameters if any are provided + query_params = None + if select or expand or filter or orderby or search or top is not None or skip is not None: + query_params = SectionsRequestBuilder.SectionsRequestBuilderGetQueryParameters() + # Set query parameters using typed object properties + if select: + query_params.select = select if isinstance(select, list) else [select] + if expand: + query_params.expand = expand if isinstance(expand, list) else [expand] + if filter: + query_params.filter = filter + if orderby: + query_params.orderby = orderby + if search: + query_params.search = search + if top is not None: + query_params.top = top + if skip is not None: + query_params.skip = skip - # Create proper typed request configuration - config = SectionsRequestBuilder.SectionsRequestBuilderGetRequestConfiguration() - config.query_parameters = query_params + # Only create configuration if needed + config = None + if query_params or headers or search: + config = SectionsRequestBuilder.SectionsRequestBuilderGetRequestConfiguration() + if query_params: + config.query_parameters = query_params - if headers: - config.headers = headers + if headers: + config.headers = headers - # Add consistency level for search operations in OneNote - if search: - if not config.headers: - config.headers = {} - config.headers['ConsistencyLevel'] = 'eventual' + # Add consistency level for search operations in OneNote + if search: + if not config.headers: + config.headers = {} + config.headers['ConsistencyLevel'] = 'eventual' response = await self.client.groups.by_group_id(group_id).onenote.sections.by_onenote_section_id(onenoteSection_id).pages.by_onenote_page_id(onenotePage_id).parent_notebook.get(request_configuration=config) return self._handle_onenote_response(response)