Skip to content

Graph sharing mechanism #957

Description

@vinistock

We want multiple tools to be able to share the Rubydex analysis graph. This comes with 2 issues:

  1. Each tool currently needs to pay the price of indexing + resolving the graph (boot time cost)
  2. Each tool holding its own graph pays the full memory price, which for large codebases can be prohibitive

We need a way of sharing the graph that hopefully allows both for eliminating the need to pay the boot cost for each tool, but also that allows us to not grow the memory usage linearly with each tool.

Ideas

Database backed cache

We might be able to take a strategy similar to Pyre check and cache the graph into a database. By tracing the graph, we should be able to partially load data from the database, so that each tools only pulls what they need and the memory growth isn't linear.

Saving boot time is also directly related to the ability of partially loading data. When launching the analysis, we need to be able to compare the previous state of the workspace (cached data) with the current state (i.e.: which documents were modified between runs). By identifying the set of documents that got modified, we can then load only the data required to analyze them, which neatly covers the use cases for linters, LSPs, MCPs, and really most CLI tools.

Pyre check uses a SQLite database with a sparse cache that remembers the list of documents that each document depends on, which allows for easy loading based on the set that got modified. The challenging parts come from the semantic differences between Ruby and Python since a lot of Ruby's data is global, which makes nailing this approach a bit challenging.

We should also experiment with ladybug DB, which is a graph database that might provide us with exactly what we need to trace the graph in the database and load only the parts that are required.

Client/server architecture

This idea means having a background process (server) that runs the analysis, while tools are clients that can query the server for information. This solves the memory sharing aspect, but there are other concerns that we would need to investigate:

  • How would a tool perform non-committed changes to the analysis without accidentally propagating changes too early to other tools? For example, an LSP handling changes that weren't committed to disk yet
  • While the memory sharing aspect is solved, the boot time cost isn't and we may still add some form of cache to speed up booting regardless
  • Communicating to the external process will probably require some form of IO and serialization, which could prove costly for query-heavy consumers like a type inference algorithm

If loading partial data proves successful, the last point may not be a concern as the tool can load all of the data upfront and then perform the analysis in-memory.

Metadata

Metadata

Assignees

No one assigned

    Labels

    hardThis issue is hard. It may involve ambiguity and challenging technical aspects

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions