# Advanced: Mod Performance Tuning

### Key Concepts

#### Secure Sandbox

PixieBrix executes text templates and Javascript code in a secure sandbox embedded in the browser extension's [offscreen document](https://developer.chrome.com/blog/Offscreen-Documents-in-Manifest-v3):

Content Script → Offscreen Document → Sandboxed Iframe → Offscreen Document → Content Script

Messaging the sandbox introduces CPU and memory overhead to serialize/deserialize data across the messenger boundaries.

### Best Practices and Tips

#### Prefer variable expressions over text templates

Variable expressions, e.g., `@foo.bar` or `@mod.myModVar?.someProperty`, do not require a call to the sandbox because they do not require code execution.

#### Merge sequential Run JavaScript Function bricks into a single brick

Each call to `Run JavaScript Function` requires a call to the sandbox. If you have multiple Run JavaScript Function bricks in a sequence, consider rewriting using a single brick that returns an object with properties.

#### Avoid passing extraneous data to the Run JavaScript Function brick

Where possible, use variable expressions to select data to pass to the Run JavaScript Function brick:

<figure><img src="/files/qMR3fOBdpWWo7ZIyIWev" alt="" width="375"><figcaption><p>Selecting data to pass to the Run JavaScript Function brick</p></figcaption></figure>

#### Remove unused brick output variables

When evaluating text templates, PixieBrix passes all available variables. Therefore, to reduce data transferred to the sandbox, remove unused Output Variables:

<figure><img src="/files/3vljhcP9tMgS8WVgRae7" alt="" width="375"><figcaption><p>Remove an Output Variable for brick by clearing the variable name</p></figcaption></figure>

#### Use nesting when operating on large data that's not required by subsequent bricks

When evaluating text templates, PixieBrix passes all available variables. If you read a large value, that value is seen by subsequent bricks at the same scope-level.

To performantly operate on a large value in the middle of mod component, nest it using the `Run Bricks` brick (or other control flow brick, e.g., `Try-Catch`). The subsequent bricks will only see the data returned from the control flow brick.

<figure><img src="/files/kf18hJpkqm4DYF0bycna" alt="" width="375"><figcaption><p>Nesting an operation on large data in the Run Bricks brick</p></figcaption></figure>

As an alternative to using nested control flow, you can overwrite the value of the variable by assigning a brick output to the same variable name.

#### Use the "Get shared page state" brick to efficiently select subsets of mod variables

When evaluating a text template with a `@mod` reference, PixieBrix transfer all mod variable state to the sandbox. That's inefficient when working with large mod variable states.

To reduce the data transmitted, use the "Get shared page state" brick to take a snapshot of a subset of mod variables, and assign them to a local variable:

<figure><img src="/files/IydsMBQHFUS5dOaAAplM" alt="" width="375"><figcaption><p>Selectively assigning mod variables to a local variable</p></figcaption></figure>

#### Toggle off non-event data for Trigger input for rapid triggers and/or heavy-weight pages

{% hint style="info" %}
Toggling off non-event data for Triggers requires Page Editor in browser extension version 2.3.3 or greater, but can be run in all versions of PixieBrix.
{% endhint %}

By default, PixieBrix includes element data in the `@input` variable for bricks. This includes data about the target element, e.g., which for Page Load and similar triggers is the entire document. For heavy pages, that can be a lot of data/information.

Therefore, for rapid triggers and/or triggers that might run on heavy-weight pages, toggle of the default input data in the Trigger configuration:

<figure><img src="/files/rs8n8KwVhskAEcTYDSRC" alt="" width="375"><figcaption><p>Toggling off non-event data for Trigger input</p></figcaption></figure>

If you need the URL or other page metadata that's generally provided in the `@input`, add the `Context reader` brick.

#### Avoid inefficient button location and Trigger selectors

PixieBrix supports [jQuery extensions](https://api.jquery.com/category/selectors/jquery-selector-extensions/) for ease of automation. However, the jQuery selector extensions not supported by native web APIs, e.g., [the MutationObserver API](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver). The PixieBrix Page Editor will warn you when using a non-native selector for a button location or trigger, for example: `:contains` , that will prevent native web APIs from being used.

Follow [best practices for writing performant CSS3 selectors](https://blogs.windows.com/msedgedev/2023/01/17/the-truth-about-css-selector-performance/)

{% hint style="warning" %}
**Common Misconception:** it's a common misconception that adding ancestors to a CSS selector speed up selector evaluation. CSS is [evaluated from right to left](https://stackoverflow.com/questions/5797014/why-do-browsers-match-css-selectors-from-right-to-left). Including ancestors can make the rule more specific, but generally decreases performance.
{% endhint %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.pixiebrix.com/developing-mods/developer-concepts/advanced-mod-performance-tuning.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
