🚀 Новая серия: от кода до железаКогда в мою жизни пришла #ИИшница, я
понял, что с ней можно очень глубоко погрузиться в любую тему: как в
устройство баз данных, так и в устройство программ😣
Мне стало интересно разложить прям по байтикам максимально простой однострочный "Hello world!"🖥
Оказалось, что он как торт 🎂 (или как лук🧅, или как огр 🤥), состоит из нескольких слоёв 🔥
Между строкой, которую ты пишешь, и транзистором, который её исполняет, ещё целая стопка: компилятор, рантайм, операционная система, и процессор. Давай вместе пройдём через все эти слои сверху вниз🔽
Начнём с самого начала. Вот файл
hello.cs:
Console.WriteLine("Hello, World!");Вот команда запуска:
dotnet run hello.cs⚙️ Что происходит под капотомКод на C# не исполняется напрямую на процессоре. Сначала компилятор (его зовут Roslyn) переводит наш код в промежуточный байт-код — IL (Intermediate Language). Это ещё не инструкции процессора, а переносимый «полуфабрикат».
Потом стартует рантайм — CoreCLR, движок .NET. Он берёт IL и уже на лету, прямо во время работы, до-компилирует его в настоящие инструкции процессора. Это называется JIT (Just-In-Time): метод компилируется в момент первого вызова.
Важная деталь про масштаб: IL-код нашей строки весит 11 байт, а рантайм, который его исполняет, весит 77 МБ. То есть наш с тобой код — это тонкая надстройка над огромным механизмом, который работает задолго до первой инструкции нашего кода и делает всё необходимое, чтобы мы увидели заветные строки на экране⚙️
Что именно он делает?Создаёт потоки Поток (thread) — это отдельная линия исполнения внутри процесса нашей программу, которую операционная система раскладывает по ядрам процессора. В одном процессе их может быть достаточно много.
Сколько?
Правильный ответ, конечно, «зависит». При отладке их можно получить целых 7! 7️⃣
И число это не фиксированное, его можно регулировать 🔧
А что ещё?Занимает память 🫡Физически процесс держит около 24 МБ, но нашей программы там почти нет: больше 20 МБ — это сам рантайм (движок CLR, JIT-компилятор, библиотека базовых типов). Из нашего там два места:
🔲стеки потоков: у каждого из семи потоков свой стек под локальные переменные и кадры вызовов функций. Под него резервируется несколько мегабайт адресов, но физически занято по паре килобайт на поток
🕳 GC-куча (heap): здесь живут объекты, созданные через
new. За этим простым словом скрывается целый мир со своими регионами:
👶gen0/👨🦱gen1/👴gen2 — здесь хранятся разные поколения «обычных» объектов (размером до 85 000 байт)
🌾 LOH — большие объекты (от 85 000 байт)
📍 POH — закреплённые (pinned) объекты
🧊 FOH — литералы и «вмороженные» объекты
И это далеко не всё!
🅰️ Что с этим делать
🟢 Программы работают на целой стопке слоёв: от кода и компилятора до операционной системы и процессора
🟢 За классическим «Hello world» стоит огромный механизм — рантайм, который делает всё необходимое, что наша программа сработала в том окружении, в котором оказалась
Если тебе что-то не понятно из вышесказанного👆 — не страшно, мне тоже многое не понятно, так что будем разбираться вместе🫂
Постепенно углубимся в каждую тему и разберёмся, как это всё работает💪
🧑💻
dp🥁
#dotnet #csharp #инженерныештучки #heavywednesday