.NET – Quá trình biên dịch: JIT (Just-In-Time) và NGEN (Native Image Generator)

compiler.NET đóng gói mã nguồn trong các file chương trình (assembly dưới dạng .exe, .dll) chứa mã lệnh Microsoft Intermediate Language (MSIL hay viết gọn là IL). Đây không phải là ngôn ngữ mà máy có thể hiểu. Vì thế khi chương trình của bạn được thực thi, một trình biên dịch JIT (Just-In-Time, còn gọi là Jitter, đây là một phần của CLR – Common Language Runtime) sẽ được gọi để biên dịch chương trình thành mã máy nhờ đó CPU có thể hiểu và thực hiện.

Về cơ bản, phương pháp này được minh họa theo mô hình sau:

JIT flow compilation

Việc biên dịch này bao gồm các công việc tối ưu mã lệnh dựa theo thông tin của máy tính (CPU, hệ điều hành) giúp chương trình hoạt động tốt hơn. Nhờ đó hiệu suất của chương trình sẽ tốt hơn với việc biên dịch hoàn toàn một chương trình ra mã máy và sử dụng ở những máy tính có cấu hình khác nhau, theo cách truyền thống. Tuy nhiên mặt trái của JIT là khiến việc khởi động chương trình sẽ trở nên chậm hơn(được gọi với thuật ngữ “startup time delay”). Hạn chế này tương đối nhỏ và có thể bỏ qua đối với các ứng dụng nhỏ.

Normal-JIT Compilation

Đây là cách mặc định được sử dụng khi bạn tạo ra các chương trình từ .NET. Khi chương trình được thực thi, JIT sẽ phải (và chỉ) biên dịch các đoạn mã (được tính theo method) cần thiết mà chương trình cần đến để thực thi. Trong quá trình thực thi, khi một method được gọi đến, JIT sẽ biên dịch toàn bộ method đó. Các method sau khi được biên dịch sẽ được lưu lại trong bộ nhớ, do đó nó không cần phải thực hiện việc biên dịch lại các đoạn mã khi chúng được thực thi nhiều lần. Ví dụ chương trình của bạn rất nhiều chức năng, nhưng nếu người dùng chỉ dùng đến chức năng A thì chỉ mỗi phần mã của A được biên dịch thành mã máy. Cách biên dịch theo này sẽ gây ra một khoảng thời gian chờ đợi mà bạn có thể nhận thấy khá rõ khi lần đầu tiên mở một chức năng nào đó của chương trình.

Khi chương trình kết thúc, các phần mã đã được biên dịch sẽ không được lưu lại. Vì thế mỗi lần chương trình khởi động, nó sẽ được biên dịch lại.

Econo-JIT Compilation

Đây là loại biên dịch cũ và không còn được hỗ trợ. Tên gọi của nó là viết tắt của “economical”, nhằm mô tả đây là một cách biên dịch “tiết kiệm”. Vấn đề “tiết kiệm” ở đây nói về bộ nhớ. Loại biên dịch này tương tự như loại thông thường trên nhưng nó không lưu lại các phần đã được biên dịch. Vì thế mỗi khi chương trình cần thực thi một đoạn mã, đoạn mã đó sẽ luôn được biên dịch lại thành mã máy.

Pre-JIT Compilation

Phương pháp này sẽ biên dịch toàn bộ chương trình trước khi chương trình đó được sử dụng. Như vậy khi chương trình được chạy, nó sẽ hoàn toàn không cần đến JIT. Và để thực hiện được cách biên dịch này, bạn cần phải dùng đến công cụ NGen.exe (Native Image Generator). NGen cũng sử dụng JIT trong quá trình biên dịch và lưu kết quả lại dưới dạng một native image và lưu trong Native Image Cache. Với phương pháp này, bạn sẽ tránh được việc “startup delay time” nhưng hiệu suất của chương trình khi chạy có thể không tốt bằng cách thông thường. Và một bất tiện nữa, bạn phải cập nhật lại native image này mỗi khi code được thay đổi.

Pre-JIT (NGEN) flow

Để sử dụng NGen, bạn có thể mở Visual Studio Command Prompt và dùng lệnh:

ngen install myapp.exe

Và lệnh sau dùng để kiểm tra xem chương trình của bạn đã được tạo native image chưa:

ngen display myapp.exe

Đọc thêm

YinYangIT Blog

1 bình luận về “.NET – Quá trình biên dịch: JIT (Just-In-Time) và NGEN (Native Image Generator)

  1. Hi anh,

    Rất cảm ơn bài viết của anh. Em đã hiểu được những khái niệm này.
    Hiện tại, Project em đang làm (khá bự) và có yêu cầu cao về startup performance. Em cũng đã tìm được cách Install NGEN này (nay mới hiểu bản chất tại sao sau khi Install NGEN nó lại nhanh như vậy).
    Ngoài ra, em đọc một số blog trên MSDN còn có cách install các assembly của app vào Global Assembly Cache (GAC). Em cũng đã có đọc qua bài này của anh: https://yinyangit.wordpress.com/2015/09/23/net-strong-named-assembly-la-gi/
    Theo em thấy thì cách này cũng có thể giúp cải thiện startup performace nhưng em chưa rõ cách thực hiện như thế nào để Install assemply lên máy bất kỳ khi deploy application. Và cách kết hợp cách này và install NGEN cho assemply trên GAC như thế nào.

    Anh có kinh nghiệm gì về vấn đề này có thể giúp đỡ, cho em một số chỉ dẫn được không ạ?
    Rất cảm ơn anh ạ. Mong nhận được câu trả lời tự anh.

Đã đóng bình luận.