-
Notifications
You must be signed in to change notification settings - Fork 1
β‘ Bolt: Reuse Gemini client to reduce overhead #23
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). | ||
|
|
||
| ## 2024-05-22 - [Gemini Client Instantiation Overhead] | ||
| **Learning:** Instantiating `google.genai.Client` costs ~80ms-220ms. Instantiating it inside loops or frequently called functions (like `generate_image`) adds up quickly. | ||
| **Action:** Instantiate the client once (e.g., in the operator or main thread) and use dependency injection to pass it to utility 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: | ||
| # β‘ Bolt: Create client once to save ~80ms per call | ||
| 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(gemini_key, prompt, client=client) | ||
| q.put(("REFINED", refined, "")) | ||
| q.put(("INFO", "Prompt refined", "")) | ||
|
|
||
|
|
@@ -103,19 +106,21 @@ 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(view_name, view_prompt, input_ref=None, client=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( | ||
| gemini_key, view_prompt, out, input_ref, client=client | ||
| ) | ||
|
Comment on lines
+116
to
+118
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. With the |
||
| 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("Front", front_prompt, None, client=client) | ||
|
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. |
||
|
|
||
| # Step 3: Generate Other Views (Parallel) | ||
| remaining_views = [ | ||
|
|
@@ -145,7 +150,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, v_name, v_prompt, front_path, client | ||
| ) | ||
|
Comment on lines
+153
to
+155
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. |
||
| ) | ||
|
|
||
| # Gather results in order | ||
|
|
||
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.
Since
generate_viewis a nested function, it can directly access theclientvariable from its parent_run_pipelinescope (this is called a closure). You don't need to passclientas an argument, which simplifies the function signature. The corresponding call sites will also need to be updated.