Proposal for Multi-Core Processing to Boost Obsidian's Efficiency

Use case or problem

When using Obsidian for creative research, I often work with multiple open windows and large canvases filled with interconnected notes. This setup allows me to visualize and manage my thoughts efficiently.

However, Obsidian’s current architecture relies primarily on a single CPU core (or, at most, a single core with two threads).

https://forum.obsidian.md/t/i-have-tested-the-13900k-3090-7950x-4090-and-7950x3d-4090-and-there-is-a-serious-issue-with-canvas-performance-no-configuration-can-smoothly-run-a-canvas-card-with-26-000-characters-of-content/81855/22

Despite my efforts to resolve this, performance issues persist. I have invested significant time and money testing and upgrading my CPU. I am currently using the latest Zen5 processor, which boasts a single-core CPU-Z benchmark score of 900. Unfortunately, even with this high-performance hardware, Obsidian still struggles to support my workflow.

This issue has been identified as a characteristic of reading mode processing.

By observing Obsidian’s CPU usage using tools like Task Manager and HWiNFO, it is clear that only one CPU core is utilized for most tasks. This limits overall performance, especially when working with multiple open windows or displaying multiple notes within a canvas. The impact is most noticeable when dealing with large lists, complex canvases with many cards, or when scrolling through content.

This issue is particularly frustrating for users with modern multi-core CPUs, as the majority of their processing power remains unused. For power users who rely on large displays, multiple Obsidian windows, and intensive visualizations, the single-core bottleneck becomes a major hindrance to productivity.


Proposed solution

To address these issues, I propose that Obsidian adopt multi-core processing strategies. This could significantly improve performance for multi-window workflows, canvas rendering, and large note lists. Below are specific recommendations for how this could be achieved:

  1. Enable Multi-Core Support for Multi-Window Usage
  • Allow each Obsidian window to run on a separate CPU core or assign different files to different CPUs.
  • Instead of sharing a single thread, multiple open windows should operate as independent threads or processes, each assigned to its own core.
  • This change would enable smoother multitasking and better responsiveness when multiple windows are open.
  1. Enable Multi-Core Rendering for Canvases
  • When displaying multiple notes within a canvas, assign each canvas card (or group of notes) to a separate core for rendering.
  • If the canvas contains multiple large cards, each card should be processed by its own thread, improving responsiveness for actions like panning, zooming, and card updates.
  • This would significantly reduce the lag users experience when working with large canvases.
  1. Task-Based Multi-Core Processing
  • Break down specific tasks, such as list rendering, file indexing, and canvas animations, into independent “jobs” that can be processed in parallel on different CPU cores.
  • This approach would reduce stuttering and improve responsiveness, especially when using performance-heavy plugins like Better Search Views, which require the rendering of large amounts of markdown content.
  • Similar task-based multi-threading is used in modern browsers and text editors, and it could be adapted to fit Obsidian’s architecture.

By enabling multi-core support, Obsidian could fully utilize the capabilities of modern CPUs, providing a smoother experience for users with large canvases, multiple windows, and extensive note collections. This would significantly reduce stuttering, speed up canvas operations, and enhance overall responsiveness.


Current workaround (optional)

  • Use fewer Obsidian windows at the same time.
  • Reduce the complexity of canvas content by using smaller, simpler notes.
  • Avoid large lists and rely on smaller notes with headers instead.
  • Manually split large notes into multiple smaller notes to reduce rendering load.

While these workarounds help to some extent, they compromise the user experience and disrupt natural workflows. For users working with large canvases or using multiple windows, these limitations are difficult to overcome.

Related Feature Requests (Optional)

The implementation of multi-core processing would mark a significant upgrade in Obsidian’s performance, allowing users to fully utilize the power of modern CPUs. This change would eliminate stuttering, enhance canvas performance, and enable a more fluid experience for users with large, interconnected note collections.

6 Likes

Have you researched what Electron is capable of doing/using? That seems the big limiting factor here.

Although I do not fully understand the detailed functionality of Electron, based on my limited knowledge, I think we can start with the simplest tasks. Since the list must be rendered all at once and cannot be split, is it possible to render different cards and notes in the canvas using different CPUs? Alternatively, can different windows or different files be rendered using different CPUs?

At the same time, I looked up some information from ChatGPT and found that Electron can support multi-core functionality and provides four methods:

  1. Each Electron window is an independent process with its own V8 engine and separate thread.
  2. By offloading intensive computational tasks to Web Workers or Node.js Worker threads, it is possible to avoid blocking the main thread.
  3. Using Node.js’s native Worker Threads module allows child threads to run in the Electron main process.
  4. Rendering can be done using the GPU instead of relying solely on CPU rendering.

(There is another issue here. In my testing, the performance of Obsidian is hardly affected by the quality of the GPU.)

1 Like

Recently, I’ve devised a method to indirectly enable Obsidian to utilize multiple cores. Although this approach won’t work for canvases and lists, it allows different windows to use separate CPUs. The method involves using mklink.

  1. Create Multiple Vaults: Copy multiple .obsidian folders and create new folders to establish new Obsidian vaults. By linking notes across vaults, they can share the same folder.
  2. Assign CPUs via Task Manager: Use the Task Manager to assign different CPUs to each vault, enabling different windows to operate on separate CPUs.

For more details, you can refer to this forum post.

In this post, I enabled two sub-vaults to be accessed by the main vault. Note that this doesn’t mean creating a new .obsidian folder under the main vault. Instead, it involves using mklink /j to link the folders that need to be shared.
However, this method could have a couple of drawbacks. First, updating configurations requires synchronization, which can be very time-consuming. Second, if multiple windows edit the same file, it may lead to sudden content loss.

1 Like

I tested it today and announced the results. This method can effectively solve the problem mentioned in this post! One window is used for previewing, and another window is used for editing. The preview window will not have any performance impact on the editing window.

Reading mode (and Canvas): Implement some form of progressive rendering for long lists

@WhiteNoise

I think this is also a very good solution! Each new window reopens the vault (similar to using copy .obsidian + mklink /j here), instead of independent windows from the vault. This way, for multiple windows, multi-core usage can be achieved!! This doesn’t require a large project, and I think the development team can consider it! The drawbacks of this method are:
firstly, it may cause different windows to edit the same file, leading to content loss, especially with plugins like Easy Typing or Update time on edit;
PS:I’m not entirely sure if it’s solely due to them. I believe it happens when two different windows open different files, and during refresh (read), modify, and save, they don’t sync. If we remove the auto-update plugins, then this synchronization issue can be resolved.

secondly, this method does not work for Canvas and list.

Currently, I manually copy .obsidian (mainly to ensure that the vault’s plugins, themes, and CSS snippets are the same) + mklink /j for the required directories. It’s important to note that Canvas cannot intelligently recognize file paths, so we must ensure the consistency of relative paths to achieve similar functionality, which is equivalent to reopening the vault (different main windows). Another issue is finding the corresponding PID. It is confirmed that AHK Window Spy cannot find the correct PID. The only way is to open a large Canvas and find the corresponding PID through high CPU usage, then allocate different cores through the task manager. However, it seems that not allocating cores might also achieve the same functionality.

1 Like

Let me add a couple of clarifying notes.

  1. Obsidian already uses some form of parallel processing/asynchronous processing in several of its components.

3.The thread you linked was made in response to your bug report has nothing to do with multi-core processing.

The problem, as I tried to explain in the other thread, is that you use huge lists.
To improve performance, Obsidian dynamically removes the blocks of texts that are not currently displayed on the screen. We do not do that for lists. Doing that for lists is hard.
For example, the level of indentation of what is on the screen depends on the part of the list that comes before it. Therefore, the part of the list that is not currently in view cannot be simply removed (from the HTML).

Another option is to optimize the rendering of extra large (HTML) documents but that is in the hands on chrome developers.

1 Like

Based on my tests, editing the same file through multiple vaults has clearly improved performance, so I’m not quite sure what you mean by “already in use” (though this method still cannot solve the canvas issue). Secondly, in my tests, Obsidian only utilizes a single core, which is a fact, with at most two threads being used (if the issue of different cards and notes in the canvas is resolved, it should utilize multiple cores).

Thirdly, I have abandoned the use of lists and switched to using H1 and H2 headers, followed by lists as a replacement. However, the performance is still under strain. Therefore, I believe that optimization has not been done effectively. If proper optimization were implemented, it should be utilizing more than one core.

Fourthly, aside from the fact that Obsidian only uses a single CPU core, it also does not make good use of the GPU for performance optimization.

So the current facts are as follows:

  1. Obsidian is a single-core program that uses one core and two threads. If this is what is meant by “Obsidian already uses some form of parallel processing/asynchronous processing in several of its components,” then the statement seems questionable.
  2. The Obsidian team has not even achieved the simplest task of assigning different files to different threads. As a result, opening the same folder with multiple vaults significantly improves editing performance. Moreover, there is no basic optimization for handling different cards and notes within the canvas.

As for plugins, it’s because Obsidian is a closed-source program, and I don’t see any intention from the official team to optimize it. Therefore, I’m considering whether it’s possible to achieve segmented rendering indirectly through plugins or explore other solutions, such as using mklink /j to enable multiple instances as a way to achieve indirect multi-core usage.

I believe that plugins are not directly related to this topic, which is why I placed them in a separate “Plugins Ideas” section. Of course, you are the administrator, and all definitions are ultimately up to you

Obsidian is a single-core program that uses one core and two threads

The Obsidian interface is basically a Chrome browser instance running an HTML, Javascript, and CSS web app that interacts with a NodeJS backend that handles reading and saving files.
Web app interfaces are by definition single-core, and there is no workaround around it.

Web workers can only be used for pure code that takes an input and returns an output, such as heavy mathematical operations.
Web workers cannot interact with the DOM, and cannot be used for rendering user interfaces.
It’s a limitation of the web platform (Javascript/HTML/CSS) and the Chrome browser.

It also does not make good use of the GPU for performance optimization.

That’s a limitation of Chrome. Again, the Obsidian interface is a Chrome instance running a web app.

“Obsidian already uses some form of parallel processing/asynchronous processing in several of its components,” then the statement seems questionable.

To verify this (1) open the dev tools using cmd/ctrl+shift+i, (2) select the sources tab (3) you’ll find web workers in the left sidebar.

The Obsidian team has not even achieved the simplest task of assigning different files to different threads

Assigning different files to different threads to improve the interface performance makes no practical sense given how web apps are built and how browsers work.

Moreover, there is no basic optimization for handling different cards and notes within the canvas

This point is valid. The canvas seems to be doing a lot of work when panning around, which should not be the case.

As for plugins, it’s because Obsidian is a closed-source program, and I don’t see any intention from the official team to optimize it

Moving (heavy pure computational) work to web workers has to be done within Obsidian itself. It’s practically impossible to implement using a plugin.
It’s like swapping out the pistons of a car engine while it’s moving. It’s not feasible.

PS: i’m not part of the Obsidian team.

3 Likes

Thank you for taking the time and effort to provide such a patient and thorough explanation. It was very helpful and gave me a deeper understanding.

I have a few questions and thoughts:

1. Multiple Vaults Approach

One possible solution I thought of is to use multiple vaults to edit files within the same folder. Do you think this approach is viable? However, I noticed an issue with this method — if there are plugins that frequently modify the files, it can lead to situations where edits are rolled back or content is cleared when editing the same file from multiple vaults. After I disabled some of the plugins that write to files, the problem seemed to improve.

2. Feasibility of the Following Suggestions

I would like to know how feasible the following suggestions are:

  • Using Web Workers
    Move the parsing of large files and Markdown preprocessing to Web Workers.
    Currently, the parsing process (converting Markdown to HTML) is done on the main thread, which blocks the UI. If this task were offloaded to a Web Worker, the UI could remain much more responsive.
  • Canvas Virtualization
    Render only the visible notes and cards, following the approach of libraries like React Virtualized.
    When panning the canvas, instead of redrawing all the notes, only redraw the parts visible within the viewport.
  • Switch to WebGL
    Although this would require a significant overhaul by the Obsidian development team, if Canvas rendering could be migrated to a WebGL rendering engine, the operations like move, pan, and zoom would become significantly smoother.
  • GPU Acceleration
    Use to pan the canvas content instead of using and .
    This forces Chrome to switch from “CPU computation” to “GPU rendering” for canvas content, potentially improving performance.transform: translate3d(x, y, 0) left top
  • Chunked/Incremental Loading
    When opening large files, use chunked loading (e.g., loading 100KB at a time) and implement virtual scrolling to load content for long paragraphs incrementally.
    (It seems that this approach is already partially implemented, as editing large files in a single file works well.)

3. Structural Limitations

Given the structural limitations of the Obsidian framework, is there any possibility of improvement? And where would be the best place to provide feedback or suggestions on this matter?

I would love to hear your thoughts on these questions if you have the time.(I feel like the development of single-core CPU performance is reaching its limit. Sigh, after your analysis, it feels hopeless, and I see no sign of any hope.)

1 Like

I am going to move this thread to meta. I think this thread is getting too technical and most of you are proposing is already implemented. Feature request should be about app features not how they are implemented.
If you have a specific use case that is very slow, search/open a a bug report and we will try to diagnose the cause.

(1) One possible solution I thought of is to use multiple vaults to edit files within the same folder. Do you think this approach is viable?

(a) Core and community plugins use internal APIs provided by Obsidian to read/write/rename files
(b) When these internal APIs are used, Obsidian triggers events describing the operation that just happened
(c) Other plugins can listen to such events and react accordingly (e.g. when a file is renamed, the Recent Files plugin would rename the file name that is saved in its data.json so that the old file name does not become stale)

Separate Obsidian instances don’t communicate with each other. Hence editing or renaming a file from one Obsidian instance is the equivalent of doing it from an external program, and won’t trigger the events. Plugins would be kept out of the loop, and this would lead to stale file names and content conflicts.

(2) Move the parsing of large files and Markdown preprocessing to Web Workers.
Currently, the parsing process (converting Markdown to HTML) is done on the main thread, which blocks the UI

Obsidian markdown editor is built using a library called codemirror and their ability to improve performance is limited to what the library exposes.

(3) Render only the visible notes and cards, following the approach of libraries like React Virtualized.

I think the canvas is not well optimized, and like WhiteNoise said you should file a bug report about performance issues (if one does not exist)

(4) if Canvas rendering could be migrated to a WebGL rendering engine, the operations like move, pan, and zoom would become significantly smoother

The canvas plugin cannot be fully migrated to WebGL as Obsidian uses codemirror which uses HTML elements.
Maybe a hybrid approach could be used where codemirror is layered on top of the WebGL canvas, but I’m not sure as I’m not familiar with the codebase.

(5) Use to pan the canvas content instead of using and.
This forces Chrome to switch from “CPU computation” to “GPU rendering” for canvas content, potentially improving performance.transform: translate3d(x, y, 0) left top

Same answer as point (3).

(6) Given the structural limitations of the Obsidian framework, is there any possibility of improvement

The canvas has room for performance improvements by making the code more efficient.

2 Likes

Thank you for your patient response. This reply is quite disappointing, and it seems there is almost no possibility for improvement. It looks like we can only hope for the single-core performance of the CPU.

1 Like