dart-code-metrics icon indicating copy to clipboard operation
dart-code-metrics copied to clipboard

[BUG] Extreme CPU and Memory Usage

Open m-skolnick opened this issue 3 years ago • 29 comments

I'm not sure if this should be a question or a bug:

Is there a way to reduce the CPU and Memory load of the plugin?

I am using VSCode. When I set dart_code_metrics as an analyzer plugin I am seeing an immediate and sustained jump in CPU and Memory usage on my Macbook Pro 2.4ghz 32gb ram.

Here is my pubspec.yaml. I'm currently on flutter version 2.5.1

name: my_flutter_package
publish_to: "none"
version: 1.0.0+1

environment:
  sdk: ">=2.12.0 <3.0.0"
  flutter: ">=2.5.0 <2.6.0"

dev_dependencies:
  dart_code_metrics: ^4.3.0
  flutter_lints: ^1.0.4

Here is my analysis_options.yaml:

include: package:flutter_lints/flutter.yaml

analyzer:
  errors:
    todo: info
    include_file_not_found: ignore
    unrelated_type_equality_checks: error
  exclude:
    - .flutter/**
    - /**/build/**
    - /**/mocks/**
    - /**/l10n/**
  plugins:
    - dart_code_metrics

dart_code_metrics:
  anti-patterns:
    - long-method
    - long-parameter-list
  metrics:
    cyclomatic-complexity: 20
    lines-of-executable-code: 50
    number-of-parameters: 4
    maximum-nesting: 5
  metrics-exclude:
    - test/**
    - .flutter/**
    - /**/build/**
    - /**/mocks/**
    - /**/l10n/**
  rules:
    - newline-before-return
    - no-boolean-literal-compare
    - no-empty-block
    - prefer-trailing-comma
    - prefer-conditional-expressions
    - no-equal-then-else

When I have the plugin in the analyzer plugins, I am seeing this in the analyzer server diagnostics:

Screen Shot 2021-10-28 at 1 20 09 PM

As soon as I remove this line and reload my VSCode, I see the following:

plugins:
  - dart_code_metrics

Screen Shot 2021-10-28 at 1 10 07 PM

m-skolnick avatar Oct 28 '21 17:10 m-skolnick

@m-skolnick please provide flutter / dart versions.

dkrutskikh avatar Oct 28 '21 18:10 dkrutskikh

@m-skolnick please provide flutter / dart versions.

Apologies.. I just added the info to my initial comment. flutter: 2.5.1

m-skolnick avatar Oct 28 '21 18:10 m-skolnick

@m-skolnick please upgrade to 2.5.3. In this version fixed analysis server memory leaks https://github.com/flutter/flutter/wiki/Hotfixes-to-the-Stable-Channel#253-october-15-2021

dkrutskikh avatar Oct 28 '21 19:10 dkrutskikh

@m-skolnick how long is the period of high CPU utilization? After a couple of minutes, is there a drop in the load?

dkrutskikh avatar Oct 29 '21 15:10 dkrutskikh

I'm still seeing the same on flutter 2.5.3.

CPU usage is definitely the highest in the first few minutes.. 90% - 190%, then it's dropping to around 40% after 5 min.

Memory however, steadily climbs to around 5,000 MB, and it stays there no matter how long I let it sit.

First 5 min: Screen Shot 2021-11-01 at 4 14 15 PM

After 10 min: Screen Shot 2021-11-01 at 4 19 32 PM

m-skolnick avatar Nov 01 '21 20:11 m-skolnick

@m-skolnick hi, so sorry for the long response. It's really hard to say, where the memory leak comes from and we'll need to investigate it better. I think one way to check would be to create an empty plugin and get the memory load metrics. I think we can do this in a few weeks.

incendial avatar Nov 29 '21 16:11 incendial

Experiencing the same issue with Flutter 2.5.3, on macOS 11.6 in VS Code 1.62.3. See analysis_options.yaml attached.

Removing the dart_code_metrics from plugins in analysis_options.yaml helps to bring resource utilization to a normal level but of course deactivates the plugin itself.

Thanks for looking into that!

analysis_options.yaml.zip

vmalyi avatar Nov 30 '21 08:11 vmalyi

@vmalyi could you test the performance with a single rule in config, for instance:

include: package:flutter_lints/flutter.yaml

analyzer:
  exclude:
    - lib/**/*.g.dart
    - lib/generated
    - test/mocked_classes.mocks.dart
  errors:
    use_key_in_widget_constructors: ignore
dart_code_metrics:
  rules:
    - newline-before-return

and check if there is any difference?

incendial avatar Nov 30 '21 17:11 incendial

Btw.. I don't think this is new. This is something I saw on old versions as well. I briefly used dart_code_metrics a few months ago and was seeing the same thing.

m-skolnick avatar Nov 30 '21 17:11 m-skolnick

Btw.. I don't think this is new.

I think the same. The only problem now is to understand from where the bug comes from: it's either the integration or our code. Since we don't save any state between file analysis, I'd bet on the integration. But we still need a proof.

incendial avatar Nov 30 '21 18:11 incendial

@vmalyi could you test the performance with a single rule in config, for instance:

include: package:flutter_lints/flutter.yaml

analyzer:
  exclude:
    - lib/**/*.g.dart
    - lib/generated
    - test/mocked_classes.mocks.dart
  errors:
    use_key_in_widget_constructors: ignore
dart_code_metrics:
  rules:
    - newline-before-return

and check if there is any difference?

Sure, @incendial!

As you asked, I've left only the newline-before-return rule and ran "Developer: Reload Window" command.

After analysis has finished (it took a couple of minutes), the analyzer identified 256 errors but resource usage according to Analysis Server Diagnostics was still high:

  • CPU: 93.2%
  • Memory: 3,301 MB
Bildschirmfoto 2021-12-06 um 16 20 54

vmalyi avatar Dec 06 '21 15:12 vmalyi

@vmalyi thank you! One last question - doest it consumes less memory / CPU with a single rule enabled or it's about the same amount?

incendial avatar Dec 06 '21 15:12 incendial

@vmalyi thank you! One last question - doest it consumes less memory / CPU with a single rule enabled or it's about the same amount?

Regardless of the number of rules activated, it consumes the same high amount of memory: the resource utilization is roughly the same with a single or multiple rules activated.

vmalyi avatar Dec 06 '21 15:12 vmalyi

Thank you! That helps a lot. It looks more like an analyzer issue, then ours. May I ask you to check one more thing?

incendial avatar Dec 06 '21 15:12 incendial

Thank you! That helps a lot. It looks more like an analyzer issue, then ours. May I ask you to check one more thing?

Sure, go ahead, @incendial, happy to help investigating this!

vmalyi avatar Dec 06 '21 15:12 vmalyi

Could you install another plugin, for example this one https://github.com/incendial/dartup-plugin-example and check how much memory it will consume? It's not published to pub, you need to set it up locally.

incendial avatar Dec 06 '21 15:12 incendial

Could you install another plugin, for example this one https://github.com/incendial/dartup-plugin-example and check how much memory it will consume? It's not published to pub, you need to set it up locally.

@incendial I gave that string_finder_plugin a try in our project and CPU utilization was a little above 100% during the 1st minute after reloading VS code window but after this (starting from approx. 1:15) normalized to 4-5% and remained at the same level.

Bildschirmfoto 2021-12-11 um 16 17 23 Bildschirmfoto 2021-12-11 um 16 17 32

vmalyi avatar Dec 11 '21 15:12 vmalyi

@vmalyi thank you! That changes everything. Looks like the problem is in our code 🤔. We'll investigate it further.

incendial avatar Dec 12 '21 07:12 incendial

I'll post an update today.

incendial avatar Dec 12 '21 08:12 incendial

I have a medium sized Flutter project and here are the results

with Dart Code Metrics from pub: Screenshot 2021-12-12 at 13 26 58

without Dart Code Metrics: Screenshot 2021-12-12 at 13 27 15

with Dart Code Metrics from local path with all our code commented, expect the plugin creation: Screenshot 2021-12-12 at 13 29 09

Still not clear why the plugin consumes additional 400 mb, but 400mb just for the integration looks a lot. Investigating further.

incendial avatar Dec 12 '21 11:12 incendial

Hm, now I'm getting ~1200MB for just plugin creation, which is very strange...

incendial avatar Dec 12 '21 12:12 incendial

Just for transparency, this problem is actively discussed in https://github.com/flutter/flutter/issues/95092

incendial avatar Dec 14 '21 12:12 incendial

Thank you. This is a good read ^

m-skolnick avatar Dec 14 '21 14:12 m-skolnick

Sure, hope we'll come to a solution together.

incendial avatar Dec 14 '21 14:12 incendial

Just for transparency, this problem is actively discussed in flutter/flutter#95092

@incendial Are you sure that this issue is related to the current one?x

MichaelDark avatar Jan 25 '22 17:01 MichaelDark

@MichaelDark not 100% sure, but it's at least something we can start with. Having a reproduction project would help.

incendial avatar Jan 25 '22 17:01 incendial

If anyone still has a memory and cpu usage issue with the version 4.11 or higher, please let us know here.

incendial avatar Apr 30 '22 07:04 incendial

Hi @incendial! I am facing this issue with dart_code_metrics: ^4.15.2 as reported here. Once I removed the dart_code_metrics from the analysis_options, the memory consumption got back to under 500Mb. Here is my full analysis_options.yaml:

include: package:flutter_lints/flutter.yaml

analyzer: 
  exclude: 
    - "lib/src/localization_gen/**"
    - "**/*.g.dart"
    - "**/*.freezed.dart"
    - "**/*routes.dart"
    - "**/*.gr.dart"
    - "**/*dependencies.config.dart"
    - "**/*generated_plugin_registrant.dart"
    - "**/*.gen.dart"
  language: 
    strict-raw-types: true
  strong-mode: 
    implicit-dynamic: true
    implicit-casts: true
  errors: 
    missing_required_param: warning
    missing_return: warning
    todo: ignore
    invalid_annotation_target: ignore    
  plugins:
     - dart_code_metrics

dart_code_metrics:
   anti-patterns:
     - long-method
     - long-parameter-list
   metrics:
     cyclomatic-complexity: 20
     halstead-volume: 150
     maximum-nesting-level: 5
     number-of-parameters: 4
     source-lines-of-code: 50
     lines-of-code: 100
     maintainability-index: 50
     number-of-methods: 10
     weight-of-class: 0.33
     technical-debt:
      threshold: 1
      todo-cost: 161
      ignore-cost: 320
      ignore-for-file-cost: 396
      as-dynamic-cost: 322
      deprecated-annotations-cost: 37
      file-nullsafety-migration-cost: 41
      unit-type: "USD"
   metrics-exclude:
     - "test/**"
   rules-exclude:
    - prefer-trailing-comma
    - prefer-match-file-name
    - prefer-single-widget-per-file
   rules:
    - newline-before-return
    - no-boolean-literal-compare
    - no-empty-block
    - prefer-conditional-expressions
    - no-equal-then-else
    - avoid-global-state
    - avoid-ignoring-return-value
    - avoid-missin-enum-constant-in-map
    - avoid-nested-conditional-expressions:
        acceptance-level:  2
    - avoid-non-null-assertion
    - avoid-throw-in-catch-block
    - avoid-unnecessary-type-assertions
    - avoid-unnecessary-type-casts
    - avoid-unrelated-type-assertions
    - avoid-unused-parameters
    - binary-expression-operand-order
    - double-literal-format
    - newline-before-return
    - no-boolean-literal-compare 
    - no-empty-block
    - no-object-declaration
    - prefer-conditional-expressions
    - prefer-correct-identifier-length:
        exceptions: [ 'z' ]
        max-identifier-length: 30
        min-identifier-length: 2
    - prefer-correct-type-name:
        excluded: [ 'exampleExclude' ]
        min-length: 3
        max-length: 40
    - prefer-first
    - prefer-last
    - always-remove-listener
    - avoid-returning-widgets:
        ignored-names:
          - testFunction
        ignored-annotations:
          - allowedAnnotation
    - avoid-unnecessary-setstate
    # - prefer-extracting-callbacks:
    #     ignored-named-arguments:
    #       - onPressed
    - avoid-wrapping-in-padding
    - prefer-const-border-radius 
    - prefer-intl-name
    - provide-correct-intl-args
    - prefer-async-await
    - prefer-immediate-return
    - avoid-collection-methods-with-unrelated-types
    - prefer-moving-to-variable
    - prefer-commenting-analyzer-ignores
    - avoid-non-ascii-symbols
    - avoid-boder-all
    - avoid-returning-widgets:
        ignored-names:
          - testFunction
        ignored-annotations:
          - allowedAnnotation
    - provide-correct-intl-args
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.0.4, on macOS 12.4 21F79 darwin-arm, locale pt-BR)
[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0-rc2)
[✓] Xcode - develop for iOS and macOS (Xcode 13.4.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2020.3)
[✓] VS Code (version 1.69.0)
[✓] Connected device (3 available)
    ! Error: iPhone de Danilo is not connected. Xcode will continue when iPhone de Danilo is connected. (code -13)
[✓] HTTP Host Availability

• No issues found!

ghost avatar Jul 11 '22 18:07 ghost

@daniloteamflow hi, thank you for reporting the issue, hoping to release the new integration in a few days https://github.com/dart-code-checker/dart-code-metrics/pull/900. It should significantly reduce the memory usage

incendial avatar Jul 13 '22 11:07 incendial

This should be fixed since 4.21.1, please update to this version. If you still experience the problem, feel free to comment or open another issue

incendial avatar Oct 14 '22 16:10 incendial