Skip to content
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

improvement: hold on to unnamed UI elements #1359

Closed
wants to merge 1 commit into from

Conversation

akshayka
Copy link
Contributor

Changes the semantics of the UIRegistry to hold on to unnamed UI elements.

This makes function call requests work on unnamed UI elements.

The registry now keeps track of all the UI elements registered to a cell, and exposes a method to unregister them. The runtime unregisters all UI elements for a cell when cell state is invalidated.

STATUS: DRAFT.

[ ] Think through second-order effects.
[ ] Might need to change destructor logic for UI elements.
[ ] Update existing tests, rewrite new ones.

Changes the semantics of the UIRegistry to hold on to unnamed UI
elements.

This makes function call requests work on unnamed UI elements.

The registry now keeps track of all the UI elements registered to a
cell, and exposes a method to unregister them. The runtime unregisters
all UI elements for a cell when cell state is invalidated.
Copy link

vercel bot commented May 11, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
marimo-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 11, 2024 5:00pm
marimo-storybook ✅ Ready (Inspect) Visit Preview 💬 Add feedback May 11, 2024 5:00pm

@akshayka
Copy link
Contributor Author

@mscolnick if you want to check if the FunctionCall in #1356 request error is due to not holding onto unnamed UI elements, you can test with this branch

@akshayka
Copy link
Contributor Author

@mscolnick I remember now why we didn't do this. This interacts badly with cached UI elements (we have a unit test that exercises this).

In particular it isn't obvious how to handle the lifecycle of UI elements:

It seems intuitive that when a cell is re-run, we purge UI elements it created from the registry — otherwise we'll have a memory leak. That's what I did in this PR.

But the user may have held onto a reference to the UI element (with functools.cache, in a list, ...). If we purged UI elements from the registry on re-run, UI registry lookups would fail with cryptic errors.

Here's the unit test that fails:

  async def test_cached_element_still_registered(                                  
      k: Kernel, exec_req: ExecReqProvider                                         
  ) -> None:                                                                       
      await k.run(                                                                 
          [                                                                        
              exec_req.get("import functools"),                                    
              exec_req.get("import marimo as mo"),                                 
              exec_req.get(                                                        
                  """                                                              
                  @functools.lru_cache                                             
                  def slider():                                                    
                      return mo.ui.slider(1, 10)                                   
                  """                                                              
              ),                                                                   
              (construct_slider := exec_req.get("s = slider()")),                  
          ]                                                                        
      )                                                                            
      # Make sure that the slider is registered                                    
      s = k.globals["s"]                                                           
      assert get_context().ui_element_registry.get_object(s._id) == s              
                                                                                   
      # Re-run the cell but fetch the same slider, since we're using               
      # functools.cache. Make sure it's still registered!                          
      await k.run([construct_slider])                                              
      assert get_context().ui_element_registry.get_object(s._id) == s 

Maybe there's a way to work around this, by tracking references/pointers in a clever way, but if there's a solution it isn't obvious to me.

@akshayka akshayka closed this May 16, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

1 participant