-
Notifications
You must be signed in to change notification settings - Fork 1
⚡ Bolt: Reuse Gemini client to save ~400ms initialization overhead #25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,7 @@ | ||
| ## 2024-05-21 - [Blender Modal Redraws] | ||
| **Learning:** Blender `modal` operators run frequently (e.g. every 0.3s). Calling `area.tag_redraw()` unconditionally in the loop forces constant viewport rendering, even when no state has changed, causing unnecessary CPU/GPU load. | ||
| **Action:** Only call `tag_redraw()` when the operator actually processes data or updates the UI state (e.g., via a `refresh_needed` flag). | ||
|
|
||
| ## 2026-02-16 - [API Client Overhead] | ||
| **Learning:** `google.genai.Client` initialization has a measurable overhead (~75-100ms). Reusing the client instance across sequential and parallel requests saves ~400ms in a multi-step generation pipeline. | ||
| **Action:** Always instantiate API clients once at the beginning of a workflow and pass them down, rather than creating them inside helper functions. | ||
| Original file line number | Diff line number | Diff line change | ||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -90,10 +90,13 @@ def execute(self, context): | |||||||||||||||
|
|
||||||||||||||||
| def _run_pipeline(self, gemini_key, meshy_key, prompt, q): | ||||||||||||||||
| try: | ||||||||||||||||
| # Create Gemini client once to save initialization time (~75ms per call) | ||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟢 It's great that you're reusing the client to improve performance. However, you are passing the
Suggested change
|
||||||||||||||||
| client = utils.get_client(gemini_key) | ||||||||||||||||
|
|
||||||||||||||||
| q.put(("INFO", "Refining prompt...", "")) | ||||||||||||||||
|
|
||||||||||||||||
| # Step 1: Refine prompt | ||||||||||||||||
| refined = utils.refine_prompt(gemini_key, prompt) | ||||||||||||||||
| refined = utils.refine_prompt(client, prompt) | ||||||||||||||||
| q.put(("REFINED", refined, "")) | ||||||||||||||||
| q.put(("INFO", "Prompt refined", "")) | ||||||||||||||||
|
|
||||||||||||||||
|
|
@@ -103,19 +106,19 @@ def _run_pipeline(self, gemini_key, meshy_key, prompt, q): | |||||||||||||||
| front_prompt = f"Front view of {refined}, white background, product shot" | ||||||||||||||||
|
|
||||||||||||||||
| # Helper to generate a single view | ||||||||||||||||
| def generate_view(view_name, view_prompt, input_ref=None): | ||||||||||||||||
| def generate_view(client, view_name, view_prompt, input_ref=None): | ||||||||||||||||
| q.put(("INFO", f"Generating {view_name}...", "")) | ||||||||||||||||
| with tempfile.NamedTemporaryFile(suffix=".png", delete=False) as tf: | ||||||||||||||||
| out = tf.name | ||||||||||||||||
|
|
||||||||||||||||
| # If it's the front view call, input_ref is None usually, | ||||||||||||||||
| # but valid for subsequent calls | ||||||||||||||||
| res_path = utils.generate_image(gemini_key, view_prompt, out, input_ref) | ||||||||||||||||
| res_path = utils.generate_image(client, view_prompt, out, input_ref) | ||||||||||||||||
| q.put(("IMAGE", f"{view_name} done", res_path)) | ||||||||||||||||
| return res_path | ||||||||||||||||
|
|
||||||||||||||||
| # Generate front view first | ||||||||||||||||
| front_path = generate_view("Front", front_prompt, None) | ||||||||||||||||
| front_path = generate_view(client, "Front", front_prompt, None) | ||||||||||||||||
|
|
||||||||||||||||
| # Step 3: Generate Other Views (Parallel) | ||||||||||||||||
| remaining_views = [ | ||||||||||||||||
|
|
@@ -145,7 +148,9 @@ def generate_view(view_name, view_prompt, input_ref=None): | |||||||||||||||
| futures = [] | ||||||||||||||||
| for v_name, v_prompt in remaining_views: | ||||||||||||||||
| futures.append( | ||||||||||||||||
| executor.submit(generate_view, v_name, v_prompt, front_path) | ||||||||||||||||
| executor.submit( | ||||||||||||||||
| generate_view, client, v_name, v_prompt, front_path | ||||||||||||||||
| ) | ||||||||||||||||
| ) | ||||||||||||||||
|
|
||||||||||||||||
| # Gather results in order | ||||||||||||||||
|
|
||||||||||||||||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -16,9 +16,9 @@ def get_client(api_key): | |||||||||||||||||||||||
| return genai.Client(api_key=api_key) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def refine_prompt(api_key, prompt): | ||||||||||||||||||||||||
| def refine_prompt(client, prompt): | ||||||||||||||||||||||||
| """Use Gemini to refine a prompt for 3D model generation.""" | ||||||||||||||||||||||||
| client = get_client(api_key) | ||||||||||||||||||||||||
| # client is passed directly | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟢 The comment
Suggested change
|
||||||||||||||||||||||||
| instruction = ( | ||||||||||||||||||||||||
| f"Refine this prompt for generating a high-quality 3D model reference image. " | ||||||||||||||||||||||||
|
|
@@ -36,15 +36,15 @@ def refine_prompt(api_key, prompt): | |||||||||||||||||||||||
| return response.text.strip() | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| def generate_image(api_key, prompt, output_path, input_image_path=None): | ||||||||||||||||||||||||
| def generate_image(client, prompt, output_path, input_image_path=None): | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
| Generate an image using Gemini. | ||||||||||||||||||||||||
| If input_image_path is provided, use it as reference for the generation. | ||||||||||||||||||||||||
| """ | ||||||||||||||||||||||||
| from google.genai import types | ||||||||||||||||||||||||
| from PIL import Image | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| client = get_client(api_key) | ||||||||||||||||||||||||
| # client is passed directly | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟢 Similar to the comment above, this comment is redundant and can be removed for cleaner code.
Suggested change
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| config = types.GenerateContentConfig( | ||||||||||||||||||||||||
| response_modalities=["Image"], | ||||||||||||||||||||||||
|
|
@@ -117,7 +117,7 @@ def generate_3d_meshy(api_key, image_paths): | |||||||||||||||||||||||
| task_id = resp.json()["result"] | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| # Adaptive polling: Check frequently at first (2s), then back off to 5s | ||||||||||||||||||||||||
| # This reduces waiting time for fast jobs without spamming the API for slow ones. | ||||||||||||||||||||||||
| # This reduces waiting time for fast jobs without spamming the API. | ||||||||||||||||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🟢 This comment change is good, but it could be slightly more descriptive.
Suggested change
|
||||||||||||||||||||||||
| intervals = [2, 2, 2, 5] | ||||||||||||||||||||||||
| default_interval = 5 | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The date
2026-02-16appears to be a typo, as it is a future date. It should likely be a date in 2024.