oxc icon indicating copy to clipboard operation
oxc copied to clipboard

linter: potential memory leak

Open cypherpower opened this issue 7 months ago • 10 comments

What version of Oxlint are you using?

0.16.7

What command did you run?

Using vs code extension and I am using a settings.json file to lint on save { "css.customData": [ ".vscode/tailwind.json" ], "editor.formatOnSave": true, // Auto fix "editor.codeActionsOnSave": { "source.fixAll.oxc": "always", "source.removeUnusedImports": "always" }, "javascript.updateImportsOnFileMove.enabled": "prompt", "editor.tabSize": 2, "editor.wordWrap": "on", "typescript.tsdk": "node_modules/typescript/lib", "typescript.enablePromptUseWorkspaceTsdk": true }

What does your .oxlintrc.json config file look like?

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": [
    "node",
    "import",
    "typescript",
    "unicorn",
    "oxc"
  ],
  // "categories": {
  //   "correctness": "off"
  // },
  "env": {
    "builtin": true,
    "browser": true,
    "commonjs": true,
    "es2024": true,
    "node": true,
    "shared-node-browser": true
  },
  "ignorePatterns": [
    "**/\\node_modules",
    "**/\\build",
    "**/.eslintcache",
    "**/.DS_Store",
    "**/.vscode-test",
    "**/.venv",
    "**/.env",
    "venv/",
    "**/.env.northAmerica",
    "**/.env.europe",
    "**/\\albert_faiss_index",
    "**/embeddings_cache.jsonl",
    "**/albert.py",
    "**/node_modules",
    "**/dist",
    "**/package-lock.json",
    "**/yarn.lock",
    "**/pnpm-lock.yaml",
    "**/bun.lockb",
    "**/output",
    "**/coverage",
    "**/temp",
    "**/.temp",
    "**/tmp",
    "**/.tmp",
    "**/.history",
    "**/.vitepress/cache",
    "**/.nuxt",
    "**/.next",
    "**/.svelte-kit",
    "**/.vercel",
    "**/.changeset",
    "**/.idea",
    "**/.cache",
    "**/.output",
    "**/.vite-inspect",
    "**/.yarn",
    "**/vite.config.*.timestamp-*",
    "**/CHANGELOG*.md",
    "**/*.min.*",
    "**/LICENSE*",
    "**/__snapshots__",
    "**/auto-import?(s).d.ts",
    "**/components.d.ts"
  ],
  "rules": {
    "array-callback-return": "error",
    "default-case-last": "error",
    "eqeqeq": [
      "error",
      "smart"
    ],
    "new-cap": [
      "error",
      {
        "capIsNew": false,
        "newIsCap": true,
        "properties": true
      }
    ],
    "no-alert": "error",
    "no-array-constructor": "error",
    "no-async-promise-executor": "error",
    "no-caller": "error",
    "no-case-declarations": "error",
    "no-class-assign": "error",
    "no-compare-neg-zero": "error",
    "no-cond-assign": [
      "error",
      "always"
    ],
    "no-console": "off",
    "no-const-assign": "error",
    "no-control-regex": "error",
    "no-debugger": "error",
    "no-delete-var": "error",
    "no-dupe-class-members": "error",
    "no-dupe-keys": "error",
    "no-duplicate-case": "error",
    "no-empty": [
      "error",
      {
        "allowEmptyCatch": true
      }
    ],
    "no-empty-character-class": "off",
    "no-empty-pattern": "error",
    "no-eval": "error",
    "no-ex-assign": "error",
    "no-extend-native": "error",
    "no-extra-boolean-cast": "error",
    "no-fallthrough": "error",
    "no-func-assign": "error",
    "no-global-assign": "error",
    "no-import-assign": "error",
    "no-invalid-regexp": "off",
    "no-irregular-whitespace": "error",
    "no-iterator": "error",
    "no-labels": [
      "error",
      {
        "allowLoop": false,
        "allowSwitch": false
      }
    ],
    "no-lone-blocks": "error",
    "no-loss-of-precision": "error",
    "no-multi-str": "error",
    "no-new": "error",
    "no-new-func": "error",
    "no-new-native-nonconstructor": "error",
    "no-new-wrappers": "error",
    "no-obj-calls": "error",
    "no-proto": "error",
    "no-prototype-builtins": "error",
    "no-redeclare": [
      "error",
      {
        "builtinGlobals": false
      }
    ],
    "no-regex-spaces": "error",
    "no-restricted-globals": [
      "error",
      {
        "message": "Use `globalThis` instead.",
        "name": "global"
      },
      {
        "message": "Use `globalThis` instead.",
        "name": "self"
      }
    ],
    "no-self-assign": [
      "error",
      {
        "props": true
      }
    ],
    "no-self-compare": "error",
    "no-shadow-restricted-names": "error",
    "no-sparse-arrays": "error",
    "no-template-curly-in-string": "error",
    "no-this-before-super": "error",
    "no-throw-literal": "error",
    "no-unexpected-multiline": "error",
    "no-unneeded-ternary": [
      "error",
      {
        "defaultAssignment": false
      }
    ],
    "no-unsafe-finally": "error",
    "no-unsafe-negation": "error",
    "no-unused-expressions": [
      "error",
      {
        "allowShortCircuit": true,
        "allowTaggedTemplates": true,
        "allowTernary": true
      }
    ],
    "no-unused-vars": [
      "error",
      {
        "args": "none",
        "caughtErrors": "none",
        "ignoreRestSiblings": true,
        "vars": "all"
      }
    ],
    "no-useless-call": "error",
    "no-useless-catch": "error",
    "no-useless-constructor": "error",
    "no-useless-rename": "error",
    "no-var": "error",
    "no-with": "error",
    "prefer-exponentiation-operator": "error",
    "prefer-promise-reject-errors": "error",
    "prefer-rest-params": "error",
    "prefer-spread": "error",
    "symbol-description": "error",
    "unicode-bom": [
      "error",
      "never"
    ],
    "use-isnan": [
      "error",
      {
        "enforceForIndexOf": true,
        "enforceForSwitchCase": true
      }
    ],
    "valid-typeof": [
      "error",
      {
        "requireStringLiterals": true
      }
    ],
    "vars-on-top": "error",
    "yoda": [
      "error",
      "never"
    ],
    "node/no-exports-assign": "error",
    "node/no-new-require": "error",
    "jsdoc/check-access": "warn",
    "jsdoc/check-property-names": "warn",
    "jsdoc/empty-tags": "warn",
    "jsdoc/implements-on-classes": "warn",
    "jsdoc/no-defaults": "warn",
    "jsdoc/require-param-name": "warn",
    "jsdoc/require-property": "warn",
    "jsdoc/require-property-description": "warn",
    "jsdoc/require-property-name": "warn",
    "jsdoc/require-returns-description": "warn",
    "import/first": "error",
    "import/no-duplicates": "error",
    "import/no-mutable-exports": "error",
    "import/no-named-default": "error",
    "import/no-self-import": "error",
    "import/no-webpack-loader-syntax": "error",
    "unicorn/consistent-empty-array-spread": "error",
    "unicorn/error-message": "error",
    "unicorn/escape-case": "error",
    "unicorn/new-for-builtins": "error",
    "unicorn/no-new-array": "error",
    "unicorn/no-new-buffer": "error",
    "unicorn/number-literal-case": "error",
    "unicorn/prefer-dom-node-text-content": "error",
    "unicorn/prefer-includes": "error",
    "unicorn/prefer-node-protocol": "error",
    "unicorn/prefer-number-properties": "error",
    "unicorn/prefer-string-starts-ends-with": "error",
    "unicorn/prefer-type-error": "error",
    "unicorn/throw-new-error": "error"
  },
  "overrides": [
    {
      "files": [
        "**/*.?([cm])ts",
        "**/*.?([cm])tsx"
      ],
      "rules": {
        "no-class-assign": "off",
        "no-const-assign": "off",
        "no-dupe-class-members": "off",
        "no-dupe-keys": "off",
        "no-func-assign": "off",
        "no-import-assign": "off",
        "no-new-native-nonconstructor": "off",
        "no-obj-calls": "off",
        "no-redeclare": "off",
        "no-setter-return": "off",
        "no-this-before-super": "off",
        "no-unsafe-negation": "off",
        "no-with": "off",
        "no-array-constructor": "off",
        "no-unused-expressions": "off",
        "no-unused-vars": "off",
        "no-useless-constructor": "off"
      }
    },
    {
      "files": [
        "**/__tests__/**/*.?([cm])[jt]s?(x)",
        "**/*.spec.?([cm])[jt]s?(x)",
        "**/*.test.?([cm])[jt]s?(x)",
        "**/*.bench.?([cm])[jt]s?(x)",
        "**/*.benchmark.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "no-unused-expressions": "off"
      }
    },
    {
      "files": [
        "**/*.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "react/jsx-no-duplicate-props": "warn",
        "react/no-array-index-key": "warn",
        "react/no-direct-mutation-state": "error",
        "react/no-string-refs": "error",
        "react-hooks/rules-of-hooks": "error"
      },
      "plugins": [
        "react"
      ]
    },
    {
      "files": [
        "**/*.md/**/*.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "no-alert": "off",
        "no-labels": "off",
        "no-lone-blocks": "off",
        "no-unused-expressions": "off",
        "no-unused-labels": "off",
        "no-unused-vars": "off",
        "unicode-bom": "off"
      }
    },
    {
      "files": [
        "**/*.d.?([cm])ts"
      ],
      "rules": {
        "import/no-duplicates": "off"
      }
    }
  ]
}

What happened?

I am seeing very high levels of memory usage with the oxc language server as a process on my computer after working in my typescript project in vscode for about an hour. It was using 6.7 GB, will send a screenshot when it happens again, (I accidentally deleted my last screenshot while creating this issue). Let me know what other details you need for me or how I can help.

cypherpower avatar Apr 26 '25 05:04 cypherpower

I tried to find a problem on the oxc_language_server side. But my htop did not reveal a problem there.

Image

I found some problems on the editor side where we do not clean up old file watchers. Hope this will help a bit 🤞

Could you please provide the following info to narrow it more down:

  • What OS are you using
  • Did you change, in the one hour, multiple times the .oxlintrc.json configuration?
  • Did you change, in the one hour, multiple times the settings.json->oxc.XYZ configuration?
  • Are you using multiple workspaces?

Sysix avatar Apr 26 '25 13:04 Sysix

I am on arch linux, I did not edit the .oxlintrc.json file at all during that time span, or the settings.json file. Also I was not using multiple workspaces, and just had one window of vscode open.

cypherpower avatar Apr 26 '25 14:04 cypherpower

Then the problem should be the linting part.

@camc314 @Boshen can it be an internal (maybe allocator?) problem when the executable is never been closed? Do not where to start :/

Sysix avatar Apr 26 '25 15:04 Sysix

Here is a screenshot of htop if it is useful

Image

cypherpower avatar Apr 26 '25 15:04 cypherpower

I am noticing that it only spikes when certain files are opened as well. I have a threejs file that open and that causes a very large spike in memory while nearly all the other files don't seem to have that problem, except for ones that also reference this one file.

I am trying to think of things that are different in this file and maybe its because it has lazy imports? const Saddle0 = lazy(() => import('../User/Saddles/Saddles/0'))

cypherpower avatar Apr 26 '25 15:04 cypherpower

Opening and closing that one file in VScode adds about 1-4MB of memory to the oxc language server process

cypherpower avatar Apr 26 '25 15:04 cypherpower

Let me working on cleaning up this file so that I can share it with you guys

cypherpower avatar Apr 26 '25 15:04 cypherpower

import { Canvas } from '@react-three/fiber'

export function ThreeDMain() {
  return (
    <Canvas
      frameloop="demand"
      resize={{ debounce: 2 }}
      shadows
      gl={{ antialias: true, preserveDrawingBuffer: true }}
      camera={{
        position: [1.5, 0.5, 3.2],
        fov: 10,
        near: 0.1,
        far: 50,
      }}
      key={1}
    >
    </Canvas>
  )
}

If you put this in a react-typescript file and open and close it multiple times you should see the memory usage spike

cypherpower avatar Apr 26 '25 15:04 cypherpower

Also it seems to be in the import plugin for oxlint, I changed the .oxlintrc.json file to this

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": [
    "import"
  ]
}

And I still get the memory leak. If I remove the import plugin and use anything else the memory leak does not happen

cypherpower avatar Apr 26 '25 15:04 cypherpower

Thanks for the deep analyze of the problem. I am not sure if we really need to resolve node_modules dependencies. What needs the import plugin for the rules, and what we can skip resolving.

https://github.com/oxc-project/oxc/blob/966fb034f365bd4695c16249df953a545861ff22/crates/oxc_linter/src/service/runtime.rs#L835-L849

Even if we need the to resolve node_modules, the memory should be free'd up after all calculations. I am not familiar with the oxc_linter runtime and oxc_resolver and wish help from the team ❤

/cc @camchenry

PS: maybe reverting https://github.com/oxc-project/oxc/pull/10406 will resolve this as a workaround?

Sysix avatar Apr 26 '25 20:04 Sysix

I updated to oxlint version 0.16.8 and I don't seem to have the problem anymore maybe that previous pull request fixed it?

cypherpower avatar Apr 27 '25 22:04 cypherpower

We made a big refactoring for the language server to prepare for multi repo setups. It could be possible that with the refactoring, the leak was being resolved.

If you are sure the problem no longer exist, feel free to close the issue as resolved ❤

Sysix avatar Apr 27 '25 23:04 Sysix

I does appear to be fixed, the language server stays around 2MB of memory even after extensive usage. Thanks for the fixes! Hyped for the 1.0 release, really pleased with the progress on the project so far!

cypherpower avatar Apr 28 '25 02:04 cypherpower

I think this bug might be present again or something else is causing a memory leak.

Image

cypherpower avatar Jun 05 '25 18:06 cypherpower

On oxlint version 0.16.8

Image

cypherpower avatar Jun 05 '25 18:06 cypherpower

Yea its the same problem, every time I open a my file that uses react-three-fiber or any file that references a component that uses it my memory usage increases by sometimes up to 40MB and does not decrease when the file gets closed. I can then reopen the file and have it spike another 40MB. Let me know if I can get you any more details. I assume something was introduced that readded this problem, because I was pretty confident this had been fixed from last time, maybe I just did not recognize it correctly though?

cypherpower avatar Jun 05 '25 18:06 cypherpower

I assume something was introduced that readded this problem

I think there was a bug which did find all .oxlintrc.json configs. So it did not enable cross file analyze. @Boshen maybe you can look into it with https://github.com/oxc-project/oxc/issues/11407 ?

Sysix avatar Jun 05 '25 18:06 Sysix

Edit: It seems to occur only when working with JSX (React .tsx files). The memory appears stable when working in pure TypeScript files.

Edit 2: The import plugin appears to be the source of the memory leak. If I disable the plugin, I cannot trigger memory usage above approximately 40 MB, so possibly a combination of the import plugin + JSX.


I am experiencing a similar issue in WebStorm.

The memory usage for oxc_language_server continues to grow with each save of new code, ~40 MB each time. After half an hour of coding, the oxc_language_service process uses ~4 GB of RAM, and is never cleaned up.

  • WebStorm latest version (Build #WS-251.26094.131, built on June 4, 2025).
  • macOS Sequoia 15.5.
  • No file watchers like "lint on save" are enabled in WebStorm.
  • Oxc latest plugin version 0.0.8 (https://plugins.jetbrains.com/plugin/27061-oxc)
  • Oxlint latest version installed in project (^0.18.0).
  • TypeScript React monorepo with 8 packages (~600 files, modern and fully updated)

The project root Oxlint config:

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": [
    "import",
    "jsdoc",
    "jsx-a11y",
    "oxc",
    "promise",
    "react",
    "react-perf",
    "typescript",
    "unicorn",
    "vitest"
  ],
  "categories": {
    "correctness": "error",
    "suspicious": "error",
    "nursery": "warn",
    "pedantic": "warn",
    "perf": "warn",
    "style": "warn",
    "restriction": "off"
  },
  "rules": {
    "eslint/array-callback-return": "off",
    "eslint/func-style": "off",
    "eslint/init-declarations": "off",
    "eslint/max-classes-per-file": "off",
    "eslint/max-depth": "off",
    "eslint/max-lines": "off",
    "eslint/max-lines-per-function": "off",
    "eslint/max-nested-callbacks": "off",
    "eslint/no-continue": "off",
    "eslint/no-duplicate-imports": "off",
    "eslint/no-magic-numbers": "off",
    "eslint/no-nested-ternary": "off",
    "eslint/no-ternary": "off",
    "eslint/no-undef": "off",
    "eslint/no-void": "off",
    "eslint/sort-imports": "off",
    "eslint/sort-keys": "off",
    "eslint/yoda": "off",

    "jest/require-hook": "off",

    "import/exports-last": "off",
    "import/group-exports": "off",
    "import/max-dependencies": "off",
    "import/no-unassigned-import": "off",

    "jsdoc/require-jsdoc": "off",
    "jsdoc/require-param": "off",
    "jsdoc/require-param-type": "off",
    "jsdoc/require-returns": "off",
    "jsdoc/require-returns-type": "off",

    "jsx_a11y/no-autofocus": "off",

    "oxc/no-async-await": "off",
    "oxc/no-rest-spread-properties": "off",

    "promise/prefer-await-to-callbacks": "off",
    "promise/prefer-await-to-then": "off",

    "typescript/ban-types": "off",
    "typescript/consistent-indexed-object-style": "off",
    "typescript/explicit-function-return-type": "off",

    "unicorn/filename-case": [
      "error",
      {
        "case": "kebabCase",
        "ignore": "^mockServiceWorker.*$"
      }
    ],
    "unicorn/no-null": "off",

    "react/jsx-curly-brace-presence": [
      "error",
      { "props": "always", "children": "never", "propElementValues": "always" }
    ],
    "react/jsx-filename-extension": ["error", { "extensions": [".jsx", ".tsx"] }],
    "react/no-array-index-key": "off",
    "react/rules-of-hooks": "error",

    "react_perf/jsx-no-jsx-as-prop": "off",
    "react_perf/jsx-no-new-function-as-prop": "off",
    "react_perf/jsx-no-new-object-as-prop": "off"
  },
  "settings": {
    "jsx-a11y": {
      "polymorphicPropName": null,
      "components": {}
    },
    "react": {
      "formComponents": [],
      "linkComponents": [
        {
          "name": "Link",
          "attribute": "to"
        }
      ]
    },
    "jsdoc": {
      "augmentsExtendsReplacesDocs": false,
      "exemptDestructuredRootsFromChecks": false,
      "ignoreInternal": false,
      "ignorePrivate": false,
      "ignoreReplacesDocs": true,
      "implementsReplacesDocs": false,
      "overrideReplacesDocs": true,
      "tagNamePreference": {}
    }
  },
  "env": {
    "builtin": true
  },
  "globals": {},
  "ignorePatterns": ["**/public", "packages/config/eslint"],
  "overrides": [
    {
      "files": ["**/*.stories.tsx"],
      "rules": {
        "react/rules-of-hooks": "off"
      }
    },
    {
      "files": ["**/*.config.*"],
      "rules": {
        "eslint/require-await": "off",
        "import/no-anonymous-default-export": "off"
      }
    }
  ]
}

App 1 Oxlint config:

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "extends": ["../../.oxlintrc.json"],
  "plugins": ["nextjs"]
}

App 2 Oxlint config (same as app 1):

{
  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "extends": ["../../.oxlintrc.json"],
  "plugins": ["nextjs"]
}

All other apps and packages use the root Oxlint config. The edited files that are causing the memory usage are in a separate app (app 3).

christofferbergj avatar Jun 07 '25 11:06 christofferbergj

One of my coworkers on the same project

Image

Can we get this fixed?

cypherpower avatar Jun 14 '25 05:06 cypherpower

Memory Leak Analysis Results

I've traced the memory leak using ASAN and found the following:

Key Findings:

  1. oxc_linter itself doesn't leak - The linter code is properly managing memory and cleaning up resources correctly.
  2. The leak is in oxc_resolver's FsCache - 99% of the leaked memory (2.3MB across 23,378 allocations) comes from oxc_resolver::fs_cache::FsCache functions: - FsCache::value - FsCachedPath::add_extension - FsCachedPath::normalize_with - Various resolver functions (resolve, require, load_as_file, etc.)
  3. This is expected behavior - The oxc_resolver intentionally caches file system metadata globally for performance optimization. This includes: - File system metadata - Path normalizations - Extension mappings - Directory listings
  4. Not a problem for normal workspaces - This caching strategy should only be problematic for very large workspaces with thousands of files. For typical projects, the performance benefits outweigh the memory usage.

ASAN Stack Trace Confirmation:

The leak traces all point to resolver operations called from Runtime::process_source_section() → resolver.resolve(dir, specifier) in /crates/oxc_linter/src/service/runtime.rs:902

The memory is intentionally retained in global cache for subsequent file resolutions, which is the designed behavior for performance optimization.

Reproduce the ASAN leak analysis

  1. rustup component add rust-std --toolchain nightly
  2. ASAN_OPTIONS=detect_leaks=1 RUSTFLAGS="-Z sanitizer=address -C link-args=-Wl,--warn-unresolved-symbols -C link-args=-fuse-ld=lld" cargo +nightly test -p oxc_linter --target aarch64-unknown-linux-gnu -Z build-std

This command will produce leak reports like this:

Indirect leak of 2 byte(s) in 2 object(s) allocated from:
    #0 0xaaaae466a1b0  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x1b1a1b0) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #1 0xaaaae5ab660c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2f6660c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #2 0xaaaae5b2447c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2fd447c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #3 0xaaaae5b23488  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2fd3488) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #4 0xaaaae5ad4614  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2f84614) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #5 0xaaaae5ad8740  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2f88740) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #6 0xaaaae50f07fc  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a07fc) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #7 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #8 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #9 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #10 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #11 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #12 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #13 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #14 0xaaaae50f073c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25a073c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #15 0xaaaae49fd590  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x1ead590) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #16 0xaaaae507fcb0  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x252fcb0) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #17 0xaaaae470cb5c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x1bbcb5c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #18 0xaaaae4723e4c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x1bd3e4c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #19 0xaaaae4d0bd4c  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x21bbd4c) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #20 0xaaaae50839e4  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x25339e4) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #21 0xaaaae4d0a2a4  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x21ba2a4) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #22 0xaaaae4e34860  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x22e4860) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #23 0xaaaae4e37628  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x22e7628) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #24 0xaaaae4e34258  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x22e4258) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #25 0xaaaae49c3bd4  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x1e73bd4) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #26 0xaaaae4cdfffc  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x218fffc) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #27 0xaaaae59bee84  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2e6ee84) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #28 0xaaaae59bc648  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2e6c648) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)
    #29 0xaaaae59cc434  (/home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838+0x2e7c434) (BuildId: b4c176f068558b6051db8be17f46521646fa1377)

Then use addr2line to map to source code:

addr2line -e /home/brooklyn/oxc/target/aarch64-unknown-linux-gnu/debug/deps/oxc_linter-b74bedbed9d89838 -f -C 0x1ea24e4 0x1ea9864 0x1ea2fa8 0x1ea5458 0x1eace74
       0x1ead5c0)
  ⎿  oxc_resolver::ResolverGeneric<C>::load_as_file
     3qzi5imqdoz6exn6luzx5wj34:?
     oxc_resolver::ResolverGeneric<C>::load_as_file_or_directory
     3qzi5imqdoz6exn6luzx5wj34:?
     oxc_resolver::ResolverGeneric<C>::require_relative
     3qzi5imqdoz6exn6luzx5wj34:?
     oxc_resolver::ResolverGeneric<C>::require_without_parse
     3qzi5imqdoz6exn6luzx5wj34:?
     oxc_resolver::ResolverGeneric<C>::require
     3qzi5imqdoz6exn6luzx5wj34:?
     oxc_resolver::ResolverGeneric<C>::resolve
     3qzi5imqdoz6exn6luzx5wj34:?

Brooooooklyn avatar Jun 16 '25 04:06 Brooooooklyn

Let me double check how the resolver interacts with the language server.

Boshen avatar Jun 16 '25 07:06 Boshen

High memory usage is associated with the mis-use of the resolver, we are getting it fixed in

  • https://github.com/oxc-project/oxc/pull/12016

We will continue tracing the memory leak after the above change.

Boshen avatar Jul 02 '25 01:07 Boshen

Thank you!!

cypherpower avatar Jul 02 '25 01:07 cypherpower

Are there any noticeable memory issues in recent versions?

Boshen avatar Aug 13 '25 04:08 Boshen

Are there any noticeable memory issues in recent versions?

I am using the latest version, deleted the node_modules and lock file in my project and reinstalled just to make sure. still have the same problem. Opening and closing the same file repeatedly causes increases on memory every time. I had one of my coworkers on a mac screen record the same issue. Typing and deleting a character in the file also causes the memory usage to increase and never go down. It takes opening a file about 15 times until the memory usage of the oxc_language server process is using 1GB of RAM.

Here the oxlint config file in my project

  "$schema": "./node_modules/oxlint/configuration_schema.json",
  "plugins": [
    "node",
    "jsdoc",
    "import",
    "unicorn"
  ],
  "categories": {
    "correctness": "off"
  },
  "env": {
    "builtin": true,
    "browser": true,
    "commonjs": true,
    "es2024": true,
    "node": true,
    "shared-node-browser": true
  },
  "ignorePatterns": [
    "**/logs",
    "**/_.log",
    "**/npm-debug.log_",
    "**/yarn-debug.log*",
    "**/yarn-error.log*",
    "**/lerna-debug.log*",
    "**/.pnpm-debug.log*",
    "app/env",
    "**/.env",
    "**/.cache",
    "**/report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json",
    "**/pids",
    "**/_.pid",
    "**/_.seed",
    "**/*.pid.lock",
    "**/lib-cov",
    "**/coverage",
    "**/*.lcov",
    "**/.nyc_output",
    "**/.grunt",
    "**/bower_components",
    "**/.lock-wscript",
    "build/Release",
    "**/build/server/",
    "**/build/client/",
    "**/node_modules/",
    "**/jspm_packages/",
    "**/web_modules/",
    "**/*.tsbuildinfo",
    "**/.npm",
    "**/.rpt2_cache/",
    "**/.rts2_cache_cjs/",
    "**/.rts2_cache_es/",
    "**/.rts2_cache_umd/",
    "**/.node_repl_history",
    "**/*.tgz",
    "**/.yarn-integrity",
    "**/.env.development.local",
    "**/.env.test.local",
    "**/.env.production.local",
    "**/.env.local",
    "**/.parcel-cache",
    "**/.next",
    "**/out",
    "**/.nuxt",
    "**/dist",
    ".vuepress/dist",
    "**/.temp",
    "**/.docusaurus",
    "**/.serverless/",
    "**/.fusebox/",
    "**/.dynamodb/",
    "**/.tern-port",
    "**/.vscode-test",
    ".yarn/cache",
    ".yarn/unplugged",
    ".yarn/build-state.yml",
    ".yarn/install-state.gz",
    "**/.pnp.*",
    "**/.idea",
    "**/.DS_Store",
    "**/.venv",
    "**/.env.json",
    "**/cdk.json",
    "**/.deploy*",
    "**/.sst",
    "**/.react-router/",
    "**/codebase.md",
    "**/node_modules",
    "**/package-lock.json",
    "**/yarn.lock",
    "**/pnpm-lock.yaml",
    "**/bun.lockb",
    "**/output",
    "**/temp",
    "**/tmp",
    "**/.tmp",
    "**/.history",
    "**/.vitepress/cache",
    "**/.svelte-kit",
    "**/.vercel",
    "**/.changeset",
    "**/.output",
    "**/.vite-inspect",
    "**/.yarn",
    "**/vite.config.*.timestamp-*",
    "**/CHANGELOG*.md",
    "**/*.min.*",
    "**/LICENSE*",
    "**/__snapshots__",
    "**/auto-import?(s).d.ts",
    "**/components.d.ts",
    "app/src/lib/*"
  ],
  "rules": {
    // "array-callback-return": "error",
    "block-scoped-var": "error",
    "default-case-last": "error",
    "eqeqeq": [
      "error",
      "smart"
    ],
    "new-cap": [
      "error",
      {
        "capIsNew": false,
        "newIsCap": true,
        "properties": true
      }
    ],
    "no-alert": "error",
    "no-array-constructor": "error",
    "no-async-promise-executor": "error",
    "no-caller": "error",
    "no-case-declarations": "error",
    "no-class-assign": "error",
    "no-compare-neg-zero": "error",
    "no-cond-assign": [
      "error",
      "always"
    ],
    "no-console": "off",
    "no-const-assign": "error",
    "no-control-regex": "error",
    "no-debugger": "error",
    "no-delete-var": "error",
    "no-dupe-class-members": "error",
    "no-dupe-keys": "error",
    "no-duplicate-case": "error",
    "no-empty": [
      "error",
      {
        "allowEmptyCatch": true
      }
    ],
    "no-empty-character-class": "off",
    "no-empty-pattern": "error",
    "no-eval": "error",
    "no-ex-assign": "error",
    "no-extend-native": "error",
    "no-extra-boolean-cast": "error",
    "no-fallthrough": "error",
    "no-func-assign": "error",
    "no-global-assign": "error",
    "no-import-assign": "error",
    "no-invalid-regexp": "off",
    "no-irregular-whitespace": "error",
    "no-iterator": "error",
    "no-labels": [
      "error",
      {
        "allowLoop": false,
        "allowSwitch": false
      }
    ],
    "no-lone-blocks": "error",
    "no-loss-of-precision": "error",
    "no-multi-str": "error",
    "no-new": "error",
    "no-new-func": "error",
    "no-new-native-nonconstructor": "error",
    "no-new-wrappers": "error",
    "no-obj-calls": "error",
    "no-proto": "error",
    "no-prototype-builtins": "error",
    "no-redeclare": [
      "error",
      {
        "builtinGlobals": false
      }
    ],
    "no-regex-spaces": "error",
    "no-restricted-globals": [
      "error",
      {
        "message": "Use `globalThis` instead.",
        "name": "global"
      },
      {
        "message": "Use `globalThis` instead.",
        "name": "self"
      }
    ],
    "no-self-assign": [
      "error",
      {
        "props": true
      }
    ],
    "no-self-compare": "error",
    "no-shadow-restricted-names": "error",
    "no-sparse-arrays": "error",
    "no-template-curly-in-string": "error",
    "no-this-before-super": "error",
    "no-throw-literal": "error",
    "no-unexpected-multiline": "error",
    "no-unneeded-ternary": [
      "error",
      {
        "defaultAssignment": false
      }
    ],
    "no-unsafe-finally": "error",
    "no-unsafe-negation": "error",
    "no-unused-expressions": [
      "error",
      {
        "allowShortCircuit": true,
        "allowTaggedTemplates": true,
        "allowTernary": true
      }
    ],
    "no-unused-vars": [
      "error",
      {
        "args": "none",
        "caughtErrors": "none",
        "ignoreRestSiblings": true,
        "vars": "all"
      }
    ],
    "no-useless-backreference": "off",
    "no-useless-call": "error",
    "no-useless-catch": "error",
    "no-useless-constructor": "error",
    "no-useless-rename": "error",
    "no-var": "error",
    "no-with": "error",
    "prefer-exponentiation-operator": "error",
    "prefer-promise-reject-errors": "error",
    "prefer-rest-params": "error",
    "prefer-spread": "error",
    "quotes": ["error", "single"],
    "symbol-description": "error",
    "unicode-bom": [
      "error",
      "never"
    ],
    "use-isnan": [
      "error",
      {
        "enforceForIndexOf": true,
        "enforceForSwitchCase": true
      }
    ],
    "valid-typeof": [
      "error",
      {
        "requireStringLiterals": true
      }
    ],
    "vars-on-top": "error",
    "yoda": [
      "error",
      "never"
    ],
    "node/no-exports-assign": "error",
    "node/no-new-require": "error",
    "jsdoc/check-access": "warn",
    "jsdoc/check-property-names": "warn",
    "jsdoc/empty-tags": "warn",
    "jsdoc/implements-on-classes": "warn",
    "jsdoc/no-defaults": "warn",
    "jsdoc/require-param-name": "warn",
    "jsdoc/require-property": "warn",
    "jsdoc/require-property-description": "warn",
    "jsdoc/require-property-name": "warn",
    "jsdoc/require-returns-description": "warn",
    // "import/consistent-type-specifier-style": [
    //   "error",
    //   "prefer-top-level"
    // ],
    "import/first": "error",
    "import/no-duplicates": "error",
    "import/no-mutable-exports": "error",
    "import/no-named-default": "error",
    "import/no-self-import": "error",
    "import/no-webpack-loader-syntax": "error",
    "unicorn/consistent-empty-array-spread": "error",
    "unicorn/error-message": "error",
    "unicorn/escape-case": "error",
    "unicorn/new-for-builtins": "error",
    "unicorn/no-instanceof-builtins": "error",
    "unicorn/no-new-array": "error",
    "unicorn/no-new-buffer": "error",
    "unicorn/number-literal-case": "error",
    "unicorn/prefer-dom-node-text-content": "error",
    "unicorn/prefer-includes": "error",
    "unicorn/prefer-node-protocol": "error",
    "unicorn/prefer-number-properties": "error",
    "unicorn/prefer-string-starts-ends-with": "error",
    "unicorn/prefer-type-error": "error",
    "unicorn/throw-new-error": "error",
    "react-hooks/rules-of-hooks": "off",
    "react-hooks/exhaustive-deps": "off"
  },
  "overrides": [
    {
      "files": [
        "**/*.?([cm])ts",
        "**/*.?([cm])tsx"
      ],
      "rules": {
        "no-class-assign": "off",
        "no-const-assign": "off",
        "no-dupe-class-members": "off",
        "no-dupe-keys": "off",
        "no-func-assign": "off",
        "no-import-assign": "off",
        "no-new-native-nonconstructor": "off",
        "no-obj-calls": "off",
        "no-redeclare": "off",
        "no-setter-return": "off",
        "no-this-before-super": "off",
        "no-unsafe-negation": "off",
        "no-with": "off",
        "no-array-constructor": "off",
        "no-unused-expressions": "off",
        "no-unused-vars": "off",
        "no-useless-constructor": "off"
      }
    },
    {
      "files": [
        "**/__tests__/**/*.?([cm])[jt]s?(x)",
        "**/*.spec.?([cm])[jt]s?(x)",
        "**/*.test.?([cm])[jt]s?(x)",
        "**/*.bench.?([cm])[jt]s?(x)",
        "**/*.benchmark.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "no-unused-expressions": "off"
      }
    },
    {
      "files": [
        "**/*.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "react/jsx-no-duplicate-props": "warn",
        "react/no-array-index-key": "warn",
        "react/no-direct-mutation-state": "error",
        "react/no-string-refs": "error",
        "react-hooks/exhaustive-deps": "warn",
        "react-hooks/rules-of-hooks": "error"
      },
      "plugins": [
        "react"
      ]
    },
    {
      "files": [
        "**/*.md/**/*.?([cm])[jt]s?(x)"
      ],
      "rules": {
        "no-alert": "off",
        "no-labels": "off",
        "no-lone-blocks": "off",
        "no-unused-expressions": "off",
        "no-unused-labels": "off",
        "no-unused-vars": "off",
        "unicode-bom": "off"
      }
    },
    {
      "files": [
        "**/*.d.?([cm])ts"
      ],
      "rules": {
        "import/no-duplicates": "off"
      }
    }
  ]
}

Do you have a basic config file I should test with to see if I also get the same problem? Perhaps it is our project's config file, it was generated using the migration script from eslint.

cypherpower avatar Aug 13 '25 05:08 cypherpower

Here's the screen recording: https://drive.proton.me/urls/BKN4BJN5JM#e4Nzpi7dLaZu

krypticbit avatar Aug 13 '25 05:08 krypticbit

It is the import plugin. If I remove the import plugin from my config file this significant increase in memory usage does not occur.

cypherpower avatar Aug 13 '25 05:08 cypherpower

This is the simplest config that will cause the same problem.

{
  "plugins": [
    "import"
  ]
}

Opening a typescript file causes an ~80MB memory usage in oxc that does not go away. And if the file is closed an reopened memory usage goes to ~240MB and so on

I have a .vscode/settings.json file which has a removeUnusedImports line which would be the only thing I can think of that might cause this kind of problem? since it seems like other users do not seem to be having this problem?

{
  "css.customData": [
    ".vscode/tailwind.json"
  ],
  "files.associations": {
    "*.css": "tailwindcss",
    "wrangler.json": "jsonc"
  },
  "editor.formatOnSave": true,
  // Auto fix
  "editor.codeActionsOnSave": {
    "source.fixAll.oxc": "always",
    "source.removeUnusedImports": "always"
  },
  "javascript.updateImportsOnFileMove.enabled": "always",
  "editor.tabSize": 2,
  "editor.wordWrap": "on",
  "typescript.tsdk": "node_modules/typescript/lib",
  "typescript.enablePromptUseWorkspaceTsdk": true,
  "python.analysis.typeCheckingMode": "basic",
  "oxc.enable": true,
  "javascript.preferences.quoteStyle": "single",
  "typescript.preferences.quoteStyle": "single"
}

Let me know if there are any other details I can share to make this problem reproducible.

cypherpower avatar Aug 13 '25 05:08 cypherpower

Even if I remove the "oxc.enable": true, and the "source.removeUnusedImports": "always" lines I still get this memory usage problem, so this probably isn't helpful.

cypherpower avatar Aug 13 '25 05:08 cypherpower

I've just had the oxc language server go up to 100GB ram in Webstorm (using 1.9.0)

fknop avatar Sep 15 '25 09:09 fknop