หลังจากปูพรมมาสองสามชั้น นี้ก็ถึงจุดไคลแม็กซ์ แล้วครับ จากบทความที่แล้ว ผมยกตัวอย่าง code ข้างล่างน่ะครับ
namespace HelloWorld
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World");
Console.WriteLine("Good Bye");
}
}
}
จาก code ผมใช้ C# compiler compile code จนได้ file HelloWorld.exe เมื่อเรา execute โปรแกรมในที่นี้ด้วยคำสั่ง
c:\>HelloWorld.exe
นี้คือสิ่งที่เกิดขึ้นในโลกของ .Net Framework
1) Step 1
ระบบปฏิบัติการ Windows จะทราบว่านี้เป็น Manage code จาก file header ของ HelloWorld.exe ระบบปฏิบัติการ Windows จึง load CLR (Common language Run time) จาก file ที่ชื่อ MSCorEE.dll
ถ้าเป็นระบบปฏิบัติการ Windows 64 bit
MSCorEE.dll จะเก็บอยู่ 2 ที่คือ %SystemRoot%\System32 (library 64 bit ของ ระบบปฏิบัติการ Windows) กับ %SystemRoot%\SysWOW64 (library 32 bit ของระบบปฏิบัติการ Windows)
ถ้าโปรแกรม Menanged code มี header เป็นแบบ 64 bit CLR จะโหลด MSCorEE.dll จาก directory %SystemRoot%\System32
ถ้าโปรแกรม Menanged code มี header เป็นแบบ 32 bit CLR จะโหลด MSCorEE.dll จาก directory %SystemRoot%\SysWOW64
ถ้าเป็นระบบปฏิบัติการ Windows 32 bit
จะไม่มี directory %SystemRoot%\SysWOW64 และ %SystemRoot%\System32 จะเป็น library 32 bit
สำหรับ %SystemRoot% ถ้าใครไม่ทราบจะหมายถึง directory ที่เก็บระบบปฏิบัติการ Windows ซึ่งส่วนใหญ่จะอยู่ที่ c:\Windows\System ยกเว้นว่าเวลาลงระบบปฏิบัติการจะเก็บไว้อีก directory อื่น
2) Step 2
เมื่อ CLR ถูก load ขึ้นมา CLR ก็จะตรวจสอบดูว่า Managed code ต้องการ .Net Framework version อะไรและทำการเปรียบเทียบ .Net Framework version ที่ได้ติดตั้งในเครื่อง ถ้าตรงกัน CLR ก็จะทำ step ถัดไปครับ
วิธีการตรวจสอบว่าที่เครื่องคอมพิวเตอร์มี .Net Framework version อะไรบ้างโดยดูจาก Registry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP
ถ้าเครื่องคอมพิวเตอร์ไม่มี .Net Framework ที่ต้องการ CLR ก็จะ report error แล้วไม่ทำงานต่อ
3) Step 3
หลังจากนั้น CLR จะทำการ load Data type ชนิดต่างๆ ของตาราง 2 ตาราง ใน Metadata (ผมมั่นใจมากว่าผู้อ่านยังไม่ลืม ... ใช่ไหมครับ)
4) Step 4
หลังจากนั้น CLR จะทำการมองหาตำแหน่ง entry point (function Main) ภายใน IL code แล้วเริ่ม compile IL code ไปเป็นภาษา Native CPU
จาก code ตัวอย่าง บรรทัดที่ Console.WriteLine("Hello World"); CLR รู้ว่า Console เป็น function ที่อยู่ใน System ก็จะทำการอ่านรายละเอียด DataType จาก metadata จากนั้น CLR จะเรียก function JITCompiler (Just In Time Compiler) เพื่อทำการ compile Console.WriteLine("Hello World"); ไปเป็นภาษา Native CPU แล้วนำ Native CPU code ไปเก็บไว้ในหน่วยความจำเพื่อส่งไปให้ CPU ประมวลผล
การ Compile IL code ไปเป็น Native CPU ระหว่าง execute โปรแกรมชนิด Managed Code เราเรียกสั้นๆ ว่า "runtime"
จากนั้น CLR จะมองไปที่บรรทัดถัดไป คือ Console.WriteLine("Good Bye"); เนื่องจาก Console ถูก compile ไปเป็น Native CPU แล้วจากบรรทัดก่อนหน้า CLR ก็จะดึง Native CPU ที่ถูก compile เสร็จแล้วไปใช้ได้เลยไม่ต้องเสียเวลา compile Console อีกรอบ
แค่นี้เราก็จะได้ภาษา Native CPU ส่งไปให้ CPU ประมวลผลแล้วครับ
เมื่อเราออกจากโปรแกรม CLR จะคืน memory ที่เก็บ Native CPU กลับไปให้กับระบบปฏิบัติการ Windows แปลว่าสิ่งที่ compile มาตอน runtime ทั้งหมดก็จะหายไปครับ
คำถาม .... ถ้าผมมีการ execute โปรแกรม HelloWord.exe เป็นครั้งที่สอง CLR ยังจำเป็นต้อง compile IL code ไปเป็น Native CPU อีกไหม
คำตอบ .... จำเป็นครับ ทุกๆ ครั้งที่มีการ execute โปรแกรม Managed Code ตัว CLR จำเป็นต้อง อ่าน metadata อ่าน IL code และ compile IL code ไปเป็น Native CPU ทุกครั้ง แม้แต่การ execute โปรแกรม Managed Code ตัวเดียวกันพร้อมกัน ตัว CLR ก็จะ compile IL ไปเป็น Native code และเก็บไว้ในหน่วยความจำที่แยกกันครับ
เหมือนๆ CLR จะทำงานซ้ำซ้อน ไหมครับ ... ใช่ครับมันทำงานซำ้ซ้อนแต่มันจะทำเฉพาะตอนเปิดโปรแกรมครั้งแรกเท่านั้นในช่วงของ runtime ดังนั้นเพื่อเป็นการเพิ่มประสิทธิภาพของ Managed Code จึงเป็นสิ่งที่จำเป็นยิ่งที่จะต้อง optimize ทั้ง IL code และ Native CPU วิธีการ optimize คือ ....
พบกันใหม่บทความหน้าครับ
TuChay
ไม่มีความคิดเห็น:
แสดงความคิดเห็น