Author: Khashayar Date: 2026-07-20 Reading time: 10 minutes

نام نوشتار: نادرستی در DMDserver و اندک راه چاره آن

پیش گفتار: چندی پیش که داشتم با Visual D کار می‌کردم و آن را به‌روزرسانی کردم، به یک نادرستی پی بردم، تاکنون به آن نپرداخته بودم، ناگهان پس از آنکه Task manager را باز کردم دیدم که 22 گیگ از پیرامون مموری‌ام را چیزی دارد پر میکند و آن DMD server بود.

Article Title: The Flaw in DMDserver and a Simple Solution for It

Introduction: Recently, while I was working with Visual D and updated it, I noticed a flaw that I hadn’t paid attention to before. Suddenly, after opening the Task Manager, I saw that something was filling up 22 GB of my memory, and that was DMD server.

فرگرد ها / Table of Contents

    ۱ – DMDserver چیست

    شاید برای شما هم همیشه پرسش باشد که پیش از اینکه build بگیرید یا تنها با نوشتن با شتابی بسیار، Error هارا IDE ها به شما نشان میدهند؟ این اندک کاری است که DMDserver و بر پایه های LSP انجام میدادند(Language Server Protocol) در گذشته برای اینکه IDE ها ساختار های کد را پیش از build گرفتن به دست بیارند، آنها را رنگی کنند(Syntax Highlighting) رفرنس ها را پیدا کنند (Find All References) باید یک سیستم دیباگر خودشان طراحی میکردند، تا در پشت زمینه کد هارا در هر دَم بسازند، اگرچه این بار افزوده برا IDE ها بود، برای همین این کار بر دوش خود کامپایلر ها افتاد که ابزاری برای این کار بسازند و IDE ها تنها با این ابزار ها پیوند پیدا کنند.

    1 – What is DMDserver

    Maybe you always wonder how IDEs show you errors so quickly while you are just typing, even before you build the project? This is exactly what DMDserver does based on LSP (Language Server Protocol). In the past, for IDEs to understand the code structure before building, color them (Syntax Highlighting), and find references (Find All References), they had to design their own debugger systems to check the code in the background every moment. Although this was an extra load on IDEs, this job was finally given to the compilers to create tools for it, so IDEs only connect to these tools.

    ۲ – AST چیست و یکی از نادرستی های DMDserver

    نوشتاری که در ویرایشگر ها مینویسید، برای رایانه تنها یک مشت نوشته ساده هستند، کامپایلر ها و سرور زبان(همانند DMDserver) نمیتواند نوشته خام را پی ببرد که چیست، برای همین نخست، ساختار کد های شما را به ساختار درختی از اشیاء (Objects) میسازد، که به آن AST (Abstract Syntax Tree) میگویند، به زبان ساده از سراسر کد های ما یک ساختاری درختی الگوریتمی میسازد، اینگونه DMDserver زمانی که این ساختار را داشته باشد زمانی که بر روی یک متغیر x کلیک میکنی با توجه به آن ساختاری که انباشت کرده در RAM پی میبرد که این x چه چیزی است مقدارش چی است بدون اینکه کامپایل کنی اطلاعات آن را به تو میدهد.

    2 – What is AST and one of the flaws of DMDserver

    The text you write in editors is just a collection of simple characters for the computer. Compilers and language servers (like DMDserver) cannot understand raw text. That is why first, they turn your code structure into a tree structure made of objects, which is called AST (Abstract Syntax Tree). Simply put, it makes an algorithmic tree out of all our code. This way, when DMDserver has this structure, if you click on a variable named ‘x’, it looks at the structure saved in the RAM and understands what ‘x’ is and what its value is without compiling, giving you the information instantly.

    ۳ – چرا پر میشود؟

    در پایه نادرستی هم در این ساختار انباشت سازی این ساختار درختی است، نادرستی از خود D یا DMD نیست، از روی اندیشه ساخت آن است، کامپایلر زبان D سرور زبانی خود را به گونه ای ساخت که شتابی بسیار در ترمینال به شما بدهد، چگونه؟ کامپایلر DMD زمانی که یک AST میسازد زمان خود را برای پاک کردن (free یا آزاد کردن) نمیگذارد یک بار میسازد و در RAM نگه میدارد یعنی حافظه را مداوم میگیرد هر چند آزاد نمیکند تا زمانی که کار پردازش تمام شود.

    زمانی که این ساختار درون dmdserver جای میگیرد، که باید در هر دَم اجرا شود (برای هر دگرگونی کوچک در کد Visual D یک بار dmdserver را اجرا میکند و یک AST نو میسازد) و هر کتابخانه ای که افزوده میشود، باید توی AST سراسر می‌آیند و همینگونه اینها در حافظه گره میخورند و ساختار DMD برای آزاد کردن تک تک آن ها ساخته نشده است، GC درونی زبان D هم نمیتواند آن ها را پاکسازی کند، پس پیامد آن این است که این ساختار های درختی مرده روی هم انباشته میشوند و در RAM گیر می‌افتند و ناگهان میبینی با 30 خط کد زدن 20 گیگابایت از رم تو پر شده است.

    این هم باید بگویم که، شاید این ساختار زبان D بسیار ناکارآمد باشد که زمینه ساز چنین نادرستی هایی میشود، اگرچه نه، برای کامپایلر های خط فرمان این شاهکار است، هرچند برای IDE ها و کار های که باید در هر دَم ساخته بشوند این نادرست چرا؟ در خط فرمان، یک کار، یک باره است، دستور را میزنی، کامپایلر در 2 دَم آغاز به کار میکند و کارش تمام میشود و می‌میرد و رم آزاد میشود، در این ساختار دیگر نیازی نیست کامپایلر زمانش را برای آزاد کردن بگذارد.

    3 – Why does it fill up?

    Basically, the flaw is inside this system of saving the tree structure. The issue is not from the D language or DMD itself; it comes from the main design idea. The D language compiler made its tool in a way to give you extreme speed in the terminal. How? When the DMD compiler builds an AST, it does not spend time to free or release the memory. It builds it once and keeps it in the RAM. This means it constantly takes memory but never releases it until the process completely finishes.

    When this structure is put inside dmdserver, which must run every second (for every small change in the code, Visual D runs dmdserver and creates a new AST) and every library that is added must be placed completely inside the AST, they get tied together in the memory. The structure of DMD is not made to free them one by one, and the internal GC of D cannot clean them either. The result is that these dead tree structures pile up on top of each other and get trapped in the RAM. Suddenly, you see that by writing just 30 lines of code, 20 GB of your RAM is filled.

    I must also say that you might think this structure of D is very inefficient because it causes such problems, but actually no, for command-line compilers it is a masterpiece. However, for IDEs and tasks that need to be rebuilt every second, this is wrong. Why? In the command line, it is a one-time job. You enter the command, the compiler starts in two moments, finishes its work, dies, and the RAM is freed. In this structure, the compiler does not need to waste time cleaning the memory.

    ۴ – در زبان های دیگر چگونه است؟

    برای خود من بسیار گیرا بود که چرا زمانی که سی شارپ کد میزنم با چنین چیزی روبه رو نمیشوم یا زبان های دیگر چرا اینگونه نیستند؟، روش C# بسیار گیراست آن از کامپایلر خاص خود (Roslyn) بهره میبرد، ناهمسو با زبان D که با هر دگرگونی سراسر یک ساختار درختی نو می‌سازد، ساختار سی شارپ به جای اینکه سراسر درخت را پاک کند تنها همان بخش دگرگون شده را دگرگون میکند و شاخه های مرده را هم به دست GC از RAM پاکسازی میشوند.

    در زبان C++ هم همانند زبان D است آن هم همانند D الگوهای سنگین و پیچیده ای دارد و میتواند رم را بسیار پر کند، اگرچه چرا چنین نمیشود؟ کامپایلر های زبان C++ چند کار دیگر را نسبت به D انجام دادن: آنها نمی‌آییند همانند زبان D سراسر بدنه توابع را مو به مو موشکافی و انباشته کنند، آنها تنها امضا و تعریف های آن را انباشت میکنند و تنها زمانی که به آن نیاز پیدا کردند، آنهارا باز کند، واژگون زبان D همه را سراسر مو به مو نگاه میکند، تا برای ویژگی های CTFE آمادگی سرشاری داشته باشد(Compile Time Function Evaluation).

    4 – How is it in other languages?

    It was very interesting to me why I never face this problem when I write C# code, or why other languages are not like this. The method of C# is very interesting; it uses its own special compiler called Roslyn. Unlike D which builds a completely new tree structure with every change, the C# structure instead of destroying the whole tree, only changes the part that was modified, and the dead branches are cleaned from the RAM by the GC.

    In C++, it is similar to the D language. It also has heavy and complex templates and can fill up the RAM quickly. However, why doesn’t this happen there? C++ compilers do a few extra things compared to D: they do not analyze and save the whole body of functions line by line like D does. They only save the signatures and declarations, and they only open them when they really need to. On the other hand, D looks at everything completely line by line to be fully ready for CTFE (Compile Time Function Evaluation) features.

    ۵ – راهکار گذرا و کوتاه من

    من خودم دانش بسیاری در این زمینه نداشتم، اندکی در این باره خواندم و چنین چیز هایی را پی بردم، در issueهای Visual D هم از این نادرستی نام برده شده بود و هاتا(حتی) در خود Visual D ویژگی افزوده شده است که پس از پر شدن از اندازه ای از RAM سراسر DMDserver را kill کند و دوباره میسازد، اگرچه برای من این کار نکرد، نمیدانم چرا، پس یک نرم افزار کوچک و ساده نوشتم برای این، یک نرم افزار کنسولی به سی شارپ(چرا با D نه؟ چون کار کردن با ویندوز با سی شارپ آسان تر و زمان کمتری میبرد تا همان را با windows api انجام بدم در D (: ) که پس از اینکه متوجه بشود dmdserver از حدی گذشت آن را میکُشد(دوباره خود Visual D آن را میسازد، هرچند نو) که میتوانید در لینک زیر آنرا نگاه کنید: DMD server Reviewer AP

    اگرچه این را هم باید بگویم، این کُشتن زوری خودش پیامد های بدی هم دارد، در زبان سی شارپ چون برای اینکار بهینه شده است، بسیار خوب کار میکند، اکنون چون در D برای این بهینه نیست ما با زور اینکار را انجام میدهیم، همین کار اندکی زمینه ساز کاهش سرعت و توان در چند دَم میشود، زمانی که می‌میرد و دوباره ساخته میشود اندکی زمان میبرد بالا بیاید و برخی از درخت ها دیگر نیستند و شاید این اندکی آزار دهنده باشد، اگرچه برای این در برنامه من یک ساختار بهینه نوشتم که اگر دید که DMD server دارد کار میکند یک اندازه ارفاق به آن می‌دهد و زمانی که دوباره آرام گرفتن با شتاب آن را میکشد اینکار نمیگذارد در میانه کار ازبین برود و آن کندی را بیش از حد حس کنید.(اگرچه اگر از حد دومی(ارفاق) هم گذشت دیگر با زور آن را میکشد.)

    5 – My temporary and short solution

    I didn’t have much knowledge in this field myself, but I read a bit about it and found out these facts. In Visual D issues, this flaw was mentioned, and even inside Visual D itself, a feature was added to kill DMDserver completely after it fills up a certain amount of RAM and rebuild it. However, for some reason, this did not work for me. So I wrote a small and simple software for this, a console application in C# (why not in D? Because working with Windows using C# is easier and takes less time than doing the same with Windows API in D :)). When it notices that dmdserver has passed the limit, it kills it (then Visual D builds it again, completely fresh). You can check it out in the link below: DMD server Reviewer AP

    However, I must say that this forced killing has its own bad consequences. In C#, since it is optimized for this task, it works very well. But now, because D is not optimized for this, we are doing it by force. This action causes a small drop in speed and performance for a few moments. When it dies and is rebuilt, it takes a little time to load, and some trees are gone, which might be a bit annoying. To fix this, I wrote an optimized structure in my program: if it sees that DMDserver is actively working, it gives it some mercy, and when it goes back to idle, it kills it quickly. This prevents it from dying in the middle of your work, so you won’t feel too much lag. (Though, if it passes the second limit or mercy limit, it will still kill it by force.)

    ۶ – در پایان (سخن پایانی)

    در پایان، خوشنود میشوم اگر در نوشته ام، جایی را نادرست نوشتم، یا من نادرست جایی را متوجه شدم، آنرا به من بگوید( در کانال تلگرام میتوانید درکامنت ها یا پیام شخصی به کانال با من در ارتباط باشید) این دنیای کامپایلر ها بسیار بزرگ و پیچیده است، از اینجا میبینیم که یک ساختار قدیمی همانند ساختاری که D برگزیده است، میتواند یقه ابزار های همچون Visual D را بگیرد، امیدوارم در نسخه های پسین DMD این را بهینه تر سازند، خودم دوست دارم بیشتر در این باره بدانم و شاید اندکی در زمان بیکاری به آن سر زدم. پیروز و پایدار باشید، بدرود.

    6 – Conclusion (Final Words)

    In the end, I will be happy if you let me know if I wrote anything wrong or if I misunderstood something (you can contact me in the Telegram channel comments or via private message). This world of compilers is very huge and complex. From this story, we can see how an old design choice, like the one D selected, can cause trouble for tools like Visual D. I hope they optimize this in future versions of DMD. I would love to learn more about this myself, and maybe I will take a look at it again in my free time. Stay successful and strong, goodbye.

    پیمایش به بالا