8000 linter: potential memory leak · Issue #10627 · oxc-project/oxc · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

linter: potential memory leak #10627

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

Open
cypherpower opened this issue Apr 26, 2025 · 18 comments
Open

linter: potential memory leak #10627

cypherpower opened this issue Apr 26, 2025 · 18 comments
Assignees
Labels
A-linter Area - Linter

Comments

@cypherpower
Copy link

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 cypherpower added the A-linter Area - Linter label Apr 26, 2025
@Sysix Sysix self-assigned this Apr 26, 2025
@Sysix Sysix mentioned this issue Apr 26, 2025
< 8000 span title="Status: Merged" data-view-component="true" class="State State--merged State--small"> Merged
@Sysix
Copy link
Member
Sysix commented Apr 26, 2025

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?

@cypherpower
Copy link
Author

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.

@Sysix
Copy link
Member
Sysix commented Apr 26, 2025

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 :/

@cypherpower
Copy link
Author

Here is a screenshot of htop if it is useful

Image

@cypherpower
Copy link
Author
cypherpower commented Apr 26, 2025

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
Copy link
Author

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

@cypherpower
Copy link
Author

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

@cypherpower
Copy link
Author
cypherpower commented Apr 26, 2025
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
Copy link
Author

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

@Sysix
Copy link
Member
Sysix commented Apr 26, 2025

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.

if let Some(resolver) = &self 8000 .resolver {
// Retrieve all dependent modules from this module.
let dir = path.parent().unwrap();
resolved_module_requests = module_record
.requested_modules
.keys()
.filter_map(|specifier| {
let resolution = resolver.resolve(dir, specifier).ok()?;
Some(ResolvedModuleRequest {
specifier: specifier.clone(),
resolved_requested_path: Arc::<OsStr>::from(resolution.path().as_os_str()),
})
})
.collect();
}

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 #10406 will resolve this as a workaround?

@Sysix Sysix removed their assignment Apr 26, 2025
@cypherpower
Copy link
Author

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?

@Sysix
Copy link
Member
Sysix commented Apr 27, 2025

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 ❤

@cypherpower
Copy link
Author

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
Copy link
Author

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

Image

@cypherpower cypherpower reopened this Jun 5, 2025
@cypherpower
Copy link
Author

On oxlint version 0.16.8

Image

@cypherpower
Copy link
Author

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?

@Sysix
Copy link
Member
Sysix commented Jun 5, 2025

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 #11407 ?

@christofferbergj
Copy link
christofferbergj commented Jun 7, 2025

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

I haven't been able to confirm the above completely yet.


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 fu)

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"]
}

The edited files that are causing the memory usage are in a separate app (app 3), that uses the root Oxlint config.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-linter Area - Linter
Projects
None yet
Development
325C

No branches or pull requests

4 participants
0