AdaCore / ada_language_server

Server implementing the Microsoft Language Protocol for Ada and SPARK
GNU General Public License v3.0
226 stars 54 forks source link

Ada_language_server process using too much RAM in linux #1053

Closed jfuica closed 1 year ago

jfuica commented 1 year ago

Hello,

I have been playing around with this promising Ada plugin for vscode (congratulations!), and apart from some "bugs" (they will be fixed for sure in future versions), i found that the plugin itself is using too much RAM (resident) in a linux machine :

Plugin version : v23.0.10. O.S. : CentOS 7.9.2009 Name: gnat_native Version: 12.1.2 (installed with alire!). Editor: Visual Studio Code 1.71.2

Using a simple default.gpr and a test.adb :

project default is

   for Source_Dirs use (".");
   for Object_Dir  use "obj";
   for Main use ("p_test.adb");

end default;

p_test.adb

with text_io;

procedure p_test is

begin

text_io.put_line ("Hi Ada");

end p_test;

Then, after executing the vscode locally in the linux machine (also happens if the vscode is launched remotely, and connected throught ssh), I realise that the resident mem usage is really high (in my opinion, for a simple programme) :

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
15296 nor 20 0 448960 13372 8688 S 0.0 0.2 0:00.38 /home/nor/.vscode/extensions/adacore.ada-23.0.10/linux/ada_languag+ 15297 nor 20 0 1073864 690764 21880 S 0.0 8.5 4:15.20 /home/nor/.vscode/extensions/adacore.ada-23.0.10/linux/ada_languag+

Therefore 0.7GB is too much, in my opinion. I can not figure out how much could be needed for large projects

--

This is what I have found:

1.- The vscode is indexing around 1500 files ( coming from the compiler sources?)

The "indexing process" takes around 4-5 minutes to be finished, using a 100% of CPU.

Note : I tried to remove this functionality setting the "ada.enableIndexing to false", but in the last version, I can not figure out how to do it.

2.- Als traces :

ALS.IN=yes > inout.txt:buffer_size=0
ALS.OUT=yes > inout.txt:buffer_size=0
>ada_ls_log.$T.txt:buffer_size=0:buffer_size=0
ALS.MAIN=yes
DEBUG.ADA_MEMORY=yes

als.xxx

[ALS.MAIN] ALS version:
[ALS.MAIN] Initializing server ...
[ALS.MAIN] GPR PATH:
[ALS.MAIN] PATH: /home/nor/bin/gnat_native_12.1.2_66b989b5/bin:/home/nor/bin/gprbuild_22.0.1_24dfc1b5/bin:/home/nor/bin:/opt/emacs/bin:.:/usr/local/bin:/usr/local/sbin:/usr/bin:/usr/sbin:/bin:/usr/lib:/usr/lib64:
[ALS.MAIN] Ada version used for predefined completion: ADA_2020 [AdaWatermark:> 35992/ 52428]
[ALS.MAIN] Initialize_Request: Request  0 /home/nor/jfuica [AdaWatermark:> 1112392/ 1898642]
[ALS.MAIN] Context root: /home/nor/jfuica [AdaWatermark:< 1104924/ 1898642]
[ALS.MAIN] Initialize_Response: Response  0  [AdaWatermark:> 1107772/ 1898642]
[ALS.MAIN] Exit_Notification:  [AdaWatermark:> 1104572/ 1898642]
[ALS.MAIN] DidChangeConfiguration_Notification: ada=(trace=(server=off)projectFile=scenarioVariables=()defaultCharset=iso-8859-1displayMethodAncestryOnNavigation=usage_and_abstract_onlyenableDiagnostics=...JSON_BOOLEAN_TYPEuseCompletionSnippets=...JSON_BOOLEAN_TYPErenameInComments=...JSON_BOOLEAN_TYPE) [AdaWatermark:> 1104618/ 1898642]
[ALS.MAIN] Project loading ... [AdaWatermark:> 1104294/ 1898642]
[ALS.MAIN] Root : /home/nor/jfuica [AdaWatermark:> 1104374/ 1898642]
[ALS.MAIN] On_DidOpenTextDocument_Notification: file:///home/nor/jfuica/p_test.adb [AdaWatermark:> 1105466/ 1898642]
[ALS.MAIN] Loading default.gpr [AdaWatermark:< 1104350/ 1898642]
[ALS.MAIN] Document_Symbols_Request: Request  1 file:///home/nor/jfuica/p_test.adb [AdaWatermark:> 1107138/ 1898642]
[ALS.MAIN] Folding_Range_Request: Request  2 file:///home/nor/jfuica/p_test.adb [AdaWatermark:> 1719638/ 2099266]
[ALS.MAIN] Document_Tokens_Range_Request: Request  3 file:///home/nor/jfuica/p_test.adb[:0:0..:18:0] [AdaWatermark:> 1744646/ 2099266]
[ALS.MAIN] Document_Tokens_Full_Request: Request  4 file:///home/nor/jfuica/p_test.adb [AdaWatermark:> 1754538/ 2099266]
[ALS.MAIN] RegisterCapability_Request: Request  2  1 [AdaWatermark:> 3645523/ 4629374]
[ALS.MAIN] RegisterCapability_Request: Request  3  1 [AdaWatermark:> 3732287/ 4629374]
[ALS.MAIN] RegisterCapability_Request: Request  4  6 [AdaWatermark:> 3738103/ 4629374]
[ALS.MAIN] In Text_Document_Did_Open [AdaWatermark:< 3730365/ 4629374]
[ALS.MAIN] Uri : file:///home/nor/jfuica/p_test.adb [AdaWatermark:< 3730365/ 4629374]
[ALS.MAIN] Finished Text_Document_Did_Open [AdaWatermark:> 7656073/ 7656457]
[ALS.MAIN] Publish_Diagnostics: file:///home/nor/jfuica/p_test.adb 1 [AdaWatermark:< 7656073/ 7656457]
[ALS.MAIN] Symbol_Response: Response  1  Is_Tree=TRUE  4 [AdaWatermark:< 7656377/ 7656765]
[ALS.MAIN] FoldingRange_Response: Response  2  2 [AdaWatermark:< 7655393/ 7659189]
[ALS.MAIN] SemanticTokens: Response  3  90 [AdaWatermark:> 7708197/ 7727769]
[ALS.MAIN] SemanticTokens: Response  4  90 [AdaWatermark:> 7708613/ 7727769]
[ALS.MAIN] WorkDoneProgress_Create_Request: Request  5 ada_ls-17538-indexing-1 [AdaWatermark:> 7800672/ 7800672]
[ALS.MAIN] Progress_Begin: ada_ls-17538-indexing-1 [AdaWatermark:> 8133005/ 8133005]

..

[ALS.MAIN] Progress_Report: ada_ls-17538-indexing-1 [AdaWatermark:> 535101345/ 535101705]
[ALS.MAIN] Progress_End: ada_ls-17538-indexing-1 [AdaWatermark:> 535177933/ 535209209]

Only final lines, inout.txt

[ALS.OUT] {"jsonrpc":"2.0","id":5,"method":"window/workDoneProgress/create","params":{"token":"ada_ls-17538-indexing-1"}} [AdaWatermark:< 7772125/ 7800881]
[ALS.IN] {"jsonrpc":"2.0","id":5,"result":null} [AdaWatermark:> 8086285/ 8086285]
[ALS.OUT] {"jsonrpc":"2.0","method":"$/progress","params":{"token":"ada_ls-17538-indexing-1","value":{"kind":"begin","title":"Indexing","percentage":0}}} [AdaWatermark:> 8198675/ 8198957]
[ALS.OUT] {"jsonrpc":"2.0","method":"$/progress","params":{"token":"ada_ls-17538-indexing-1","value":{"kind":"report","message":"3/1564 files","percentage":0}}} [AdaWatermark:> 9248777/ 9251181]
[ALS.OUT] {"jsonrpc":"2.0","method":"$/progress","params":{"token":"ada_ls-17538-indexing-1","value":{"kind":"report","message":"6/1564 files","percentage":0}}} [AdaWatermark:> 15714673/ 15715133]

...

[ALS.OUT] {"jsonrpc":"2.0","method":"$/progress","params":{"token":"ada_ls-17538-indexing-1","value":{"kind":"report","message":"1561/1564 files","percentage":99}}} [AdaWatermark:> 535102015/ 535102193]
[ALS.OUT] {"jsonrpc":"2.0","method":"$/progress","params":{"token":"ada_ls-17538-indexing-1","value":{"kind":"end"}}} [AdaWatermark:< 535177697/ 535209209]

Best Regards.

setton commented 1 year ago

Hello @jfuica !

The memory consumption is expected - we're indexing the Ada runtime (for instance the sources for Ada.Text_IO), to support cross-references for the full closure of the program. This explains the around 0.7 gb of memory consumption, and is expected.

However it should be much faster than this - measured in seconds rather than minutes. Unless you are investigating memory consumption, you should deactivate the trace DEBUG.ADA_MEMORY, which introduces a very significant performance overhead.

Best regards,

Nicolas

setton commented 1 year ago

You can also control the runtime indexing via the trace ALS.RUNTIME_INDEXING. Turning this off means less memory footprint, but operations such as "Find all references" on runtime entities won't return complete results within the body of the runtime.

raph-amiard commented 1 year ago

The memory consumption is expected - we're indexing the Ada runtime (for instance the sources for Ada.Text_IO), to support cross-references for the full closure of the program. This explains the around 0.7 gb of memory consumption, and is expected.

Also, to complete @setton 's answer, the GNAT ada runtime is at least ~350000 lines, so you should expect this to scale quite well on big projects, since this seems to be one of your worries.

jfuica commented 1 year ago

Hello, Nicolas, Raphël,

"ada.enableIndexing": false => The vscode does not recognise this config variable, but it works.
+
ALS.RUNTIME_INDEXING=no 

It does the trick!, now, my RAM usage is very low, and the time it takes to start the ada_language_server plugin is fine (at least for small projects).

--

However, if I test this configuration in a big project, the amount of RAM used is around 2-3GB. Therefore, my concern is : if the amount needed for every instance of the ada_language is 3 GB * let say 5 programmers = 15GB would be needed in the server only for programming.

I am still investigating why is this RAM usage so high, and If I can reduce it removing some directories from the *.gpr.

Thanks for your quick response, it was really helpful!

raph-amiard commented 1 year ago

However, if I test this configuration in a big project, the amount of RAM used is around 2-3GB. Therefore, my concern is : if the amount needed for every instance of the ada_language is 3 GB * let say 5 programmers = 15GB would be needed in the server only for programming.

That's indeed a concern, but unfortunately one that we don't know how to solve yet. Ideally we would be able to share a libadalang instance amongst all servers for a same project, but we don't have the technology to do that - at least not in the foreseeable future :)

Short term, the ALS has been conceived more as something that is supposed to run on your personal dev machine, where memory usage should be reasonable given current machine specs and size of projects.