---
url: https://nsh.dev/ar/docs/performance-report
description: "أرقام مقاسة لتطبيقات NSH - تكاليف الـ commit والإطار (frame) من خطوط الأساس الخاصة بـ NSH، ومعدل إطارات المعرض (gallery) واستهلاك المعالج والذاكرة صفحةً بصفحة على Linux وmacOS وWindows وiOS - مع طريقة إعادة إنتاجها."
---

# تقرير الأداء

كلفة تطبيقات NSH مقيسة بالأرقام. لمعرفة كيف يحافظ NSH على سرعتها وكيف تقيس أداء تطبيقك، راجع [الأداء](https://nsh.dev/translations/ar/docs/performance.md).

<a id="baselines"></a>

## القياسات المرجعية

من القياسات المرجعية الخاصة بـ NSH (على Apple silicon ما لم يُذكر خلاف ذلك):

| السيناريو | الأرقام |
|---|---|
| تطبيق عدّاد، بلا واجهة (headless) (debug) | أول إطار ~0.5–0.65 ms (58 عملية / 49 عنصر تركيب)؛ نقرة واحدة ~0.15 ms |
| تطبيق عدّاد، Mac Catalyst (release) | أول إطار ~1.05–1.15 ms (منها نحو 0.7 ms لتخطيط 10 نصوص بواسطة CoreText لأول مرة)؛ نقرة واحدة ~0.12 ms |
| قائمة صور المعرض، بلا واجهة (headless) (debug) | أول إطار 653 عملية / 224 عقدة، ~2.7 ms |
| تمرير قائمة الصور، Catalyst (release) | إعادة ربط صف واحد أثناء التمرير البطيء ~0.4 ms؛ شاشة كاملة من ~32 صفًا عند تمرير سريع 0.9–1.6 ms |
| تمرير قائمة الصور، محاكي Android (arm64، release) | إعادة ربط صف واحد ~0.3–0.4 ms (JS ~60 µs) |
| بدء تشغيل المحرك (release) | ~75–155 µs؛ الواجهات العامة (`fetch`، `URL`، ...) لا تكلّف شيئًا حتى أول استخدام، ثم ~90 µs |
| إعادة التحميل الفوري (Hot reload) | ~120 ms من حفظ الملف حتى تشغيل النسخة الجديدة؛ وتطبيق التحديث 0.2–0.5 ms |

## Linux (GTK 4)

قيست على حاسوب مكتبي يعمل بنظام Linux (x86_64، 24 خيطًا، معالج رسوميات NVIDIA)، بنسخ release، والمعرض في نافذة 1896 × 1030 على شاشة 120 Hz، وكل قراءة أُخذت تلقائيًا بواسطة `examples/gallery/tools/perf.py` (`nsh test --target linux --fps`، سطر واحد كل ثانية؛ المعالج CPU يخص العملية بأكملها، كنسبة مئوية من نواة واحدة). *Frame p95* هو زمن الخيط الرئيسي لكل إطار مرسوم عند المئين 95: وإذا كان أقل من 8.3 ms فإن الإطار يتسع داخل تحديث الشاشة بمعدل 120 Hz.

<a id="animated-demos"></a>

### العروض المتحركة

<div class="data-table">

| العرض | FPS | Frame p95 | CPU |
|---|---|---|---|
| Stocks: 22 خطًا مصغّرًا حيًّا، ومخطط خلال اليوم، ودفتر أوامر، وشريط صفقات | 117–120 | 5–6 ms | 25–29% (1200 × 800)، 28–32% (1896 × 1030) |
| Stocks، والنافذة تملأ شاشة 4K بمعدل 144 Hz وبمقياس 1.6× | 143–145 | 4.1–4.4 ms | 26–29% |
| Canvas: مقياس، وساعة، ومصفوفة نقاط | 120 | 2.6–4.4 ms | 5–10% |
| Animations: ثلاث حلقات أصلية، وسوابض (springs)، وتسلسلات | 120 | 2.0 ms | 12–13% |

</div>

<a id="every-page"></a>

### كل صفحة

كل صفحة من صفحات المعرض، عند فتحها وأثناء تمرير الاختبار لها، في نافذة 1200 × 800 على شاشة 144 Hz (الجهاز نفسه). يرسم NSH إطارًا فقط عندما يتغير شيء على الشاشة، لذا فإن *FPS* هنا هو المعدل أثناء حدوث حركة: إطار واحد لكل فترة وسيطة بين الإطارات المرسومة (`perf.py` الخاص بـ `moving`)؛ وعند 144 للشاشة، يأتي كل إطار من إطارات الحركة أو التمرير بعد تحديث واحد من الإطار السابق. *أكثر من تحديث واحد* هي نسبة الإطارات التي استغرقت أكثر من تحديث واحد (6.9 ms). يُشغَّل GIF وWebP في Images بمعدلات إطاراتها الخاصة (نحو 50 FPS هنا)، وكذلك الفيديو. صفحات Physics وOverlays وMenus قصيرة: ففي 1200 × 800 يصل التمرير إلى نهايتها خلال بضعة إطارات، لذلك تُقاس في نافذة 900 × 500 حيث يتوفر لها متسع للتمرير.

<div class="data-table">

| الصفحة | مصدر الإطارات | FPS | Frame p95 | أكثر من تحديث واحد | CPU |
|---|---|---|---|---|---|
| Stocks | بيانات حية، حلقات أصلية | 144 | 4.1 ms | 0% | 26% |
| Stocks، تمرير | بيانات حية، تمرير | 144 | 4.1 ms | 0% | 25% |
| Photos، تمرير | تمرير | 144 | 2.8 ms | 2% | 9% |
| Lists، تمرير | تمرير | 143 | 1.7 ms | 0% | 7% |
| Scrolling، تمرير | تمرير | 144 | 1.6 ms | 1% | 4% |
| Navigation، تمرير | تمرير | 143 | 1.7 ms | 0% | 2% |
| Form، تمرير | تمرير | 144 | 1.3 ms | 0% | 4% |
| Resizable، تمرير | تمرير | 143 | 0.6 ms | 0% | 1% |
| Dock، تمرير | تمرير | 142 | 0.5 ms | 1% | 1% |
| Gestures | سوابض (springs)، حلقة نابضة | 144 | 1.6 ms | 0% | 1–5% |
| Physics، تمرير | تمرير (نافذة 900 × 500) | 144 | 1.6 ms | 1% | 1% |
| Animations | حلقات أصلية | 144 | 2.6 ms | 0–1% | 5% |
| Canvas، تمرير | تمرير، حلقات أصلية | 144 | 4.2 ms | 0% | 1–4% |
| Styles، تمرير | تمرير | 144 | 2.3 ms | 2% | 3% |
| Tailwind | أدوات `animate-*` المساعدة (utilities) | 144 | 1.7 ms | 0% | 3–8% |
| Text، تمرير | تمرير | 144 | 1.9 ms | 0% | 4% |
| Text View، تمرير | تمرير | 141 | 1.8 ms | 2% | 7% |
| Images، تمرير | تمرير، إطارات GIF وWebP | 143 | 2.9 ms | 2% | 8% |
| Components، تمرير | تمرير | 144 | 1.4 ms | 0% | 3% |
| Overlays، تمرير | تمرير (نافذة 900 × 500) | 144 | 1.7 ms | 0% | 2% |
| Menus، تمرير | تمرير (نافذة 900 × 500) | 144 | 1.9 ms | 0% | 2% |
| Controls | انتقالات | 144 | 0.9 ms | 0% | 1–4% |
| Web and video | إطارات الفيديو، الصفحة | 135–142 | 1.0 ms | 0% | 7–8% |

</div>

<a id="memory"></a>

### الذاكرة

في حالة السكون، بعد 3 ثوانٍ من البدء (مشغّلات release، نافذة 480 × 640). *Private* هي الذاكرة التي تملكها العملية وحدها (USS)؛ أما *resident* فتضيف صفحات المكتبات المشتركة (GTK، وتعريف GPU)، التي يشاركها كل تطبيق GTK على الجهاز:

<div class="data-table">

| التطبيق | المُصيِّر (Renderer) | Private (USS) | Resident (RSS) |
|---|---|---|---|
| تطبيق Rust (`nsh init --template rust`) | GL (`ngl`) | ~49 MB | ~142 MB |
| تطبيق Rust | Cairo (`GSK_RENDERER=cairo`) | ~28 MB | ~95 MB |
| عدّاد TSX (`examples/counter`) | GL | ~79 MB | ~166 MB |
| نافذة GTK 4 بتسمية واحدة، للمقارنة | Vulkan / Cairo | ~62 / ~40 MB | ~132 / ~109 MB |

</div>

إعادة زيارة صفحة لا تضيف ذاكرة؛ أما أول زيارة لصفحة فتزيد حجم العملية بمقدار ما تخزّنه عمدًا في الذاكرة المؤقتة (صور مفكوكة الترميز، بحد أقصى 128 MB) وبالمكتبات التي تُحمَّل عند أول استخدام (WebKitGTK لعروض الويب).

<a id="app-size"></a>

### حجم التطبيق

تطبيق hello world أنشأه `nsh init` بكل قالب، وتطبيقان يستخدمهما الناس، كما يبنيهما `nsh package --target linux` لمعمارية x86_64. المشغّل (runner) هو الملف التنفيذي الوحيد للتطبيق؛ والأرشيف هو `.tar.gz` الذي يُوزَّع به. تُبنى تطبيقات hello world مع تحسين وقت الربط (link-time optimization) وتُجرَّد من الرموز (`CARGO_PROFILE_RELEASE_LTO=fat`، `CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1`، `CARGO_PROFILE_RELEASE_STRIP=true`):

<div class="data-table">

| التطبيق | لغة الكتابة | المشغّل | الأرشيف |
|---|---|---|---|
| Hello world (`--template rust`) | Rust | 16.5 MB | 7.5 MB |
| Hello world (`--template ts`) | TSX، على QuickJS | 25.7 MB | 11.6 MB |
| Hello world (`--template mixed`) | TSX وحزمة Rust (crate) | 25.8 MB | 11.7 MB |
| [sysmon](https://github.com/huacnlee/sysmon) 0.1.3 | Rust | 20.9 MB بعد التجريد | 9.7 MB |
| [Omasend](https://github.com/huacnlee/omasend) 0.2.0 | Rust | 22.3 MB | 9.8 MB |

</div>

تحتوي مشغّلات TSX على بيئة QuickJS التشغيلية والوحدات الأصلية والمُصيِّر؛ أما شيفرة التطبيق نفسه فهي حزمته (bundle) الموجودة بجانب المشغّل، وحجمها أقل من 1 KB في تطبيق hello world.

ما الذي يصنع هذه الأرقام:

- **المُصيِّر**: مع تعريف NVIDIA يرسم NSH بمُصيِّر GL الخاص بـ GSK، وتكلفة إطاراته جزء يسير من تكلفة مُصيِّر Vulkan هناك (عرض Animations: ~1 ms من الرسم لكل إطار بدلًا من ~9.5 ms). ولا يزال `GSK_RENDERER` هو من يختار.
- **تحويل Canvas إلى نقاط (rasters)**: يُحوَّل كل canvas إلى نقاط مرة واحدة في بلاطات بحجم 256 px محفوظة على GPU. وتعيد القيمة المتحركة رسم المنطقة التي تغطيها العمليات التي تقرؤها فقط، فوق البكسلات المحفوظة للجزء الثابت من الرسم؛ وأي canvas خارج مجال الرؤية ينتظر حتى يُمرَّر إلى العرض.
- **مسارات تُحفظ جانبًا مرة واحدة**: `fillRect` و`fillText` بعد مسار طويل يتركانه في مكانه حتى يُستخدم مجددًا (خط من 400 نقطة ثم 240 شريطًا: 0.63 ms).

## macOS (AppKit)

قيست على MacBook Pro (Apple M3، 24 GB) على شاشته المدمجة ProMotion بمعدل 120 Hz، بنسخ release، والمعرض في نافذة 1200 × 800، وكل قراءة أُخذت تلقائيًا بواسطة `examples/gallery/tools/perf.py` (`nsh test --target macos
--fps`، سطر واحد كل ثانية؛ المعالج CPU يخص العملية بأكملها، كنسبة مئوية من نواة واحدة، وGPU حصتها من معالج الرسوميات). المراحل هي أزمنة الخيط الرئيسي لكل إطار: *tick* (الحركات الأصلية لرابط العرض display link) و*canvas* (إعادة تشغيل الرسومات).

<a id="animated-demos-1"></a>

### العروض المتحركة

<div class="data-table">

| العرض | FPS | Frame p95 | CPU | GPU |
|---|---|---|---|---|
| Stocks: 22 خطًا مصغّرًا حيًّا، ومخطط خلال اليوم، ودفتر أوامر، وشريط صفقات | 120 | 2.7–3.7 ms | 33–36% | 18–22% |
| Canvas: مقياس، وساعة، ومصفوفة نقاط | 119–120 | 0.6–0.7 ms | 4–7% | 0% |
| Animations: ثلاث حلقات أصلية، وسوابض (springs)، وتسلسلات | 119–120 | 0.3–1.6 ms | 5–8% | 0% |

</div>

في Stocks يبلغ زمن الخيط الرئيسي للإطار نحو 1.6 ms للـ ticks، منها ~0.45 ms لإعادة تشغيل الأجزاء المتحركة من canvases؛ أما بقية كل canvas فيرسمه Core Animation على خيوطه الخاصة.

<a id="every-page-1"></a>

### كل صفحة

كل صفحة من صفحات المعرض، عند فتحها وأثناء تمرير الاختبار لها، في نافذة 1200 × 800 نفسها. وكما في Linux، فإن *FPS* هو المعدل أثناء حدوث حركة (إطار واحد لكل فترة وسيطة بين الإطارات المرسومة)؛ وعند 120 للشاشة، يأتي كل إطار من إطارات الحركة أو التمرير بعد تحديث واحد من الإطار السابق. *أكثر من تحديث واحد* هي نسبة الإطارات التي استغرقت أكثر من تحديث واحد (8.3 ms). الصفحة الساكنة لا ترسم أي إطار وتستهلك 2–5% من CPU. يُشغَّل GIF وWebP في Images عبر Core Animation، والفيديو عبر AVFoundation، بمعدلات إطاراتها الخاصة.

<div class="data-table">

| الصفحة | مصدر الإطارات | FPS | Frame p95 | أكثر من تحديث واحد | CPU |
|---|---|---|---|---|---|
| Stocks | بيانات حية، حلقات أصلية | 120 | 3.2 ms | 0% | 35% |
| Stocks، تمرير | بيانات حية، تمرير | 120 | 3.5 ms | 0% | 36% |
| AI Chat، تمرير | تمرير | 120 | 2.4 ms | 1% | 5% |
| Photos، تمرير | تمرير | 120 | 1.4 ms | 0% | 10% |
| Lists، تمرير | تمرير | 120 | 1.6 ms | 0% | 8% |
| Scrolling، تمرير | تمرير | 120 | 2.7 ms | 0% | 6% |
| Navigation، تمرير | تمرير | 120 | 0.2 ms | 0% | 4% |
| Form، تمرير | تمرير | 120 | 0.6 ms | 0% | 5% |
| Resizable، تمرير | تمرير | 120 | 0.3 ms | 0% | 4% |
| Dock، تمرير | تمرير | 120 | 0.3 ms | 1% | 5% |
| Gestures | سوابض (springs)، حلقة نابضة | 120 | 0.4 ms | 0% | 4% |
| Physics، تمرير | تمرير | 120 | 0.3 ms | 0% | 4% |
| Animations | حلقات أصلية | 120 | 0.3 ms | 0% | 5% |
| Canvas، تمرير | تمرير، حلقات أصلية | 120 | 1.2 ms | 0% | 7% |
| Styles، تمرير | تمرير، تحويل متمايل | 120 | 1.0 ms | 0% | 6% |
| Tailwind | أدوات `animate-*` المساعدة (utilities) | 120 | 0.5 ms | 0% | 4% |
| Text، تمرير | تمرير | 120 | 0.3 ms | 0% | 5% |
| Text View، تمرير | تمرير | 120 | 0.7 ms | 0% | 5% |
| Images، تمرير | تمرير | 120 | 0.4 ms | 0% | 5% |
| Components، تمرير | تمرير | 120 | 0.3 ms | 0% | 5% |
| Overlays، تمرير | تمرير | 120 | 0.3 ms | 0% | 4% |
| Menus، تمرير | تمرير | 120 | 0.3 ms | 0% | 5% |
| Controls | انتقالات | 120 | 0.3 ms | 0% | 4% |
| Web and video، تمرير | تمرير | 120 | 0.2 ms | 0% | 6% |
| System | `requestAnimationFrame`، مؤقّتات | 120 | 0.2 ms | 0% | 3% |
| Standard APIs، تمرير | تمرير | 120 | 0.3 ms | 0% | 5% |
| Storage، تمرير | تمرير | 120 | 0.3 ms | 0% | 5% |

</div>

<a id="memory-1"></a>

### الذاكرة

في حالة السكون، بعد 3 ثوانٍ من البدء (مشغّلات release). *Footprint* هي الذاكرة التي يحاسب بها macOS العملية (ما يعرضه Activity Monitor)؛ أما *resident* فتضيف صفحات المكتبات المشتركة للنظام:

<div class="data-table">

| التطبيق | النافذة | Footprint | Resident (RSS) |
|---|---|---|---|
| تطبيق Rust (`nsh init --template rust`) | 1200 × 800 | ~19 MB | ~86 MB |
| عدّاد TSX (`examples/counter`) | 1200 × 800 | ~20 MB | ~89 MB |
| نافذة AppKit بتسمية واحدة، للمقارنة | 480 × 640 | ~17 MB | ~80 MB |

</div>

خلال جولة المعرض تشغل العملية ما بين 84 و230 MB حتى صفحة Canvas، ثم ~350–360 MB ابتداءً من صفحة Text View، وذلك مع ما تخزّنه عمدًا في الذاكرة المؤقتة (صور مفكوكة الترميز، بحد أقصى 128 MB؛ ومستندات صفحة Text View) ومع الأطر (frameworks) التي تُحمَّل عند أول استخدام (WebKit لعروض الويب)؛ أما نقاط raster الخاصة بصفحة Canvas، التي تصل إلى ~310 MB عند ظهور الـ canvases الثلاثة على الشاشة، فتزول عند إغلاق الصفحة.
<a id="app-size-1"></a>

### حجم التطبيق

تطبيقات hello world التي ينشئها `nsh init` بكل قالب، كما يبنيها `nsh package --target macos` لمعالجات Apple
silicon (arm64)، مع تحسين وقت الربط (link-time optimization) وإزالة الرموز كما في Linux، إضافةً إلى التطبيقين المذكورين أعلاه كما يُشحنان لمعالجات Apple
silicon. الملف التنفيذي هو المشغّل (runner) داخل `.app`؛ والملف المضغوط هو `.app` بعد ضغطه (`ditto -c -k`):

<div class="data-table">

| التطبيق | لغة الكتابة | الملف التنفيذي | مضغوط `.app` |
|---|---|---|---|
| Hello world (`--template rust`) | Rust | 12.4 MB | 6.0 MB |
| Hello world (`--template ts`) | TSX على QuickJS | 19.8 MB | 9.5 MB |
| Hello world (`--template mixed`) | TSX وحزمة Rust (crate) | 19.8 MB | 9.5 MB |
| [sysmon](https://github.com/huacnlee/sysmon) 0.1.3 | Rust | 21.6 MB | 8.4 MB (`.tar.gz` الخاص بإصداره) |
| [Omasend](https://github.com/huacnlee/omasend) 0.2.0 | Rust | 18.4 MB | 9.7 MB (`.tar.gz` الخاص بإصداره) |

</div>

ما الذي يحقق هذه الأرقام:

- **إطارات للتغييرات فقط**: يعمل display link أثناء تشغيل حركة أصلية (native animation) ويتوقف معها؛ وتتوقف الحركة مع صفحتها (حذف العرض الخاص بها ينهي إطاراتها المفتاحية، وتتوقف الحلقة في `cleanup` الخاص بمكوّنها).
- **رسم الـ canvas حيث يكلّف أقل**: الـ canvas الذي يُرسم كثيرًا (حركة، بيانات حية) يُرسم على خيوط Core
  Animation (`drawsAsynchronously`)، مما يُبقي الخيط الرئيسي حرًا؛ أما الذي يُعاد رسمه بين الحين والآخر فيُرسم
  فورًا، دون ذاكرة الرسوميات التي يحتفظ بها الرسم غير المتزامن. وتعيد القيمة المتحركة رسم المنطقة التي تغطيها
  العمليات التي تقرؤها فقط.
- **الاحتفاظ بأجزاء الـ canvas الثابتة**: متى بقي الرسم دون تغيير، يُحفظ الجزء الطويل الذي يسبق أول عملية متحركة
  كطبقة (layer)؛ ويرسم كل إطار هذه الطبقة ويعيد تشغيل الجزء المتحرك المتبقي فقط، فورًا على الخيط الرئيسي (مقياس
  صفحة Canvas وساعتها ومصفوفة نقاطها: بلا عمل على GPU وبنصف الذاكرة).
- **رسم المحتوى عند تغيّره**: تُرسم النصوص والـ canvas في طبقات خاصة بها، وتُرسم من جديد عند تغيّر محتواها أو
  حجمها، لا عند تحريكها أو تمريرها.

## Windows (Win32, Direct2D)

القياسات على حاسوب مكتبي بنظام Windows 11 (Intel Core i7-13700KF، ذاكرة 32 GB، NVIDIA GeForce RTX 3060 Ti) بشاشة 4K وتردد 144 Hz
بتكبير 150%، وبنسخ release، ومعرض الأمثلة (gallery) في نافذة 1200 × 800 (1800 × 1200 بكسل)، وكل قراءة تُؤخذ تلقائيًا بواسطة
`examples/gallery/tools/perf.py` (`nsh test --target windows --fps`، سطر واحد كل ثانية؛ استهلاك CPU للعملية كاملة، بنسبة مئوية
من نواة واحدة). المراحل هي ما يستغرقه الخيط الرئيسي لكل إطار: *paint* (رسم Direct2D للنافذة) وضمنه
*canvas* (تسجيل الرسومات وإعادة تشغيلها).

<a id="animated-demos-2"></a>

### العروض المتحركة

<div class="data-table">

| العرض | FPS | زمن الإطار p95 | الرسم / canvas لكل إطار | CPU |
|---|---|---|---|---|
| Stocks: 22 مخططًا مصغرًا حيًا، ومخطط خلال اليوم، ودفتر أوامر، وشريط صفقات | 144 | 3.7–4.3 ms | 1.4 / 0.13 ms | 36–43% |
| Canvas: مقياس، وساعة، ومصفوفة نقاط | 144 | 1.0–2.0 ms | 0.8–1.4 / 0.05 ms | 21–35% |
| Animations: ثلاث حلقات أصلية، وsprings، وتسلسلات | 144 | 1.0–3.6 ms | 0.9–1.9 ms | 20–41% |

</div>

ينفّذ Stocks من 16 إلى 17 عملية commit في الثانية، تستغرق كل منها حتى 2.1 ms في JS و1.7 ms في النواة على خيط المحرّك (p95).

> [!NOTE]
> الصفحات التي تحرّك فيها الحركات العروض عبر مساحات كبيرة تستهلك CPU أكثر هنا مما في Linux وmacOS (Animations بين 20–41%
> مقابل 5–13%، وGestures بنسبة 36% مقابل 1–5%). يعيد إطار Windows رسم كل عرض، بواسطة Direct2D على الخيط الرئيسي،
> فوق المناطق التي تغيّرت: حلقة تتسع تُعيد رسم البطاقة التي تحتها في كل إطار. أما في macOS فيحرّك Core Animation
> الطبقات التي يحتفظ بها ويكبّرها ويُخفتها على GPU دون إعادة رسمها، وفي Linux يحتفظ GSK
> بعُقد العرض (render nodes) لما لم يتغيّر. كما تحتسب الأرقام 144 إطارًا في الثانية بدقة 1800 × 1200 بكسل.

<a id="every-page-2"></a>

### كل صفحة

كل صفحة من صفحات المعرض، عند فتحها وأثناء تمرير الاختبار لها، في نافذة 1200 × 800 نفسها. كما في Linux و
macOS، *FPS* هو المعدّل أثناء وجود حركة (إطار واحد لكل فجوة وسيطة بين الإطارات المرسومة)؛ وعند 144 للشاشة،
يأتي كل إطار من حركة أو تمرير بعد تحديث واحد من سابقه. *تجاوز تحديثًا واحدًا* هي نسبة الإطارات
التي استغرقت أكثر من تحديث واحد (6.9 ms). الصفحة الساكنة لا ترسم أي إطار وتستهلك 0–2% من CPU. صور GIF وWebP في صفحة Images
تعمل بمعدلات إطاراتها الخاصة (نحو 40 FPS هنا). تُقاس صفحات Physics وOverlays وMenus وStorage في نافذة 900 × 500،
حيث تتسع للتمرير.

<div class="data-table">

| الصفحة | مصدر الإطارات | FPS | زمن الإطار p95 | تجاوز تحديث واحد | CPU |
|---|---|---|---|---|---|
| Stocks | بيانات حية، حلقات أصلية | 144 | 3.9 ms | 0% | 36% |
| Stocks, scrolling | بيانات حية، تمرير | 144 | 4.3 ms | 0% | 43% |
| Photos, scrolling | تمرير | 143 | 2.1 ms | 0% | 9% |
| Lists, scrolling | تمرير | 144 | 2.0 ms | 1% | 19% |
| Scrolling, scrolling | تمرير | 143 | 2.1 ms | 0% | 7% |
| Navigation, scrolling | تمرير | 144 | 0.8 ms | 0% | 9% |
| Form, scrolling | تمرير | 144 | 0.8 ms | 0% | 12% |
| Resizable, scrolling | تمرير | 143 | 0.4 ms | 0% | 4% |
| Dock, scrolling | تمرير | 144 | 0.5 ms | 1% | 5% |
| Gestures | springs، حلقة نابضة | 144 | 1.8 ms | 0% | 36% |
| Physics, scrolling | تمرير (نافذة 900 × 500) | 144 | 0.8 ms | 0% | 4% |
| Animations | حلقات أصلية | 144 | 1.0 ms | 0% | 28% |
| Canvas, scrolling | تمرير، حلقات أصلية | 144 | 2.0 ms | 0% | 35% |
| Styles, scrolling | تمرير، تحويل متمايل | 144 | 2.1 ms | 0% | 39% |
| Tailwind | أدوات `animate-*` المساعدة | 144 | 0.6 ms | 0% | 19% |
| Text, scrolling | تمرير | 144 | 1.6 ms | 0% | 8% |
| Text View, scrolling | تمرير | 144 | 1.1 ms | 0% | 10% |
| Images, scrolling | تمرير، إطارات GIF وWebP | 143 | 4.8 ms | 2% | 23% |
| Components, scrolling | تمرير | 144 | 1.0 ms | 1% | 11% |
| Overlays, scrolling | تمرير (نافذة 900 × 500) | 144 | 0.6 ms | 0% | 1% |
| Menus, scrolling | تمرير (نافذة 900 × 500) | 144 | 0.6 ms | 0% | 2% |
| Controls | انتقالات | 117–144 | 1.5 ms | 0% | 22% |
| Web and video, scrolling | تمرير | 144 | 1.6 ms | 0% | 15% |
| System | `requestAnimationFrame`، مؤقتات | 144 | < 0.1 ms | 0% | 1% |
| Storage, scrolling | تمرير (نافذة 900 × 500) | 144 | 0.5 ms | 0% | 1% |

</div>

<a id="memory-2"></a>

### الذاكرة

في حالة السكون، بعد 3 ثوانٍ من البدء (مشغّلات release، نافذة 1200 × 800). *Private working set* هي الذاكرة التي تستخدمها
العملية وحدها (عمود Memory في Task Manager)؛ و*private bytes* ما حجزته منها؛ و*working set* تضيف صفحات
مكتبات النظام التي تتشاركها مع عمليات أخرى (Direct3D وDirect2D وDirectWrite وبرنامج تشغيل GPU):

<div class="data-table">

| التطبيق | Private working set | Private bytes | Working set |
|---|---|---|---|
| تطبيق Rust (`nsh init --template rust`) | ~14 MB | ~60 MB | ~53–71 MB |
| عدّاد TSX (`examples/counter`) | ~15 MB | ~61 MB | ~56–71 MB |

</div>

خلال جولة المعرض يبلغ working set نحو 108–115 MB في Stocks، ونحو 230 MB من صفحة Canvas، ونحو 320–340 MB من
صفحة Text View، ونحو 390–405 MB بعد أن تفتح Web and video عنصر WebView2 (الذي تعمل صفحاته في عمليات WebView2 الخاصة به)،
مع ما تخزّنه مؤقتًا عن قصد (الصور المفكوكة، بحد أقصى 128 MB؛ ومستندات صفحة Text View).

<a id="app-size-2"></a>

### حجم التطبيق

تطبيقات hello world التي ينشئها `nsh init` بكل قالب، كما يبنيها `nsh package --target windows` لمعمارية x86_64
(مشغّلات Rust مع تحسين وقت الربط وإزالة الرموز، كما في Linux). الملف التنفيذي هو `<Name>.exe` التطبيق؛
والملف المضغوط هو `.zip` المكتوب بجانب مجلده:

<div class="data-table">

| التطبيق | لغة الكتابة | الملف التنفيذي | الملف المضغوط |
|---|---|---|---|
| Hello world (`--template rust`) | Rust | 15.0 MB | 6.7 MB |
| Hello world (`--template ts`) | TSX على QuickJS | 28.6 MB | 12.4 MB |
| Hello world (`--template mixed`) | TSX وحزمة Rust (crate) | 26.3 MB | 11.5 MB |

</div>

ما الذي يحقق هذه الأرقام:

- **إطارات للتغييرات فقط، تُرسم حيث تغيّرت فقط**: يعمل المؤقّت (ticker) المتزامن مع المُركِّب (compositor) أثناء تشغيل حركة
  أصلية أو انتقال أو دالة رد نداء للإطار. يرسم الإطار مناطق العروض التي تغيّرت (حيث كانت
  وحيث صارت)، فوق البكسلات التي تحتفظ بها النافذة، ولا يقدّم للمُركِّب إلا هذه المناطق (Stocks:
  نحو 34 عرضًا في الإطار).
- **يسجّل الـ canvas جزأه المتحرك**: يُسجَّل الرسم كقوائم أوامر Direct2D، متجهيًا وحادًا عند أي
  مقياس. وعندما تتغيّر قيمة متحركة، لا يُعاد تسجيل إلا العمليات ابتداءً من أول عملية تقرأ قيمة متحركة؛
  أما ما يسبقها فيُحتفظ به (Stocks: نحو 26 ms من التسجيل في الثانية لـ 22 مخططًا مصغرًا نابضًا
  والمخطط الرئيسي).
- **يُرسم ما يظهر فقط**: تُستثنى من الإطار العروض الأبناء لعرض تمرير أو عرض قص (clipping) التي تقع خارج
  مجال الرؤية، ولا ترسم العروض التي لا محتوى خاصًا بها أكثر من خلفيتها وحدودها.

## iOS (UIKit)

القياسات في محاكي iOS (iPhone 18 Pro Max، على MacBook Pro المذكور أعلاه)، بنسخ release، وبالجولة نفسها
(`perf.py --target ios`: `nsh test --target ios --fps`، لمسات إصبع كما يتلقاها UIKit). يعرض المحاكي
بتردد 60 Hz؛ وعلى iPhone بشاشة ProMotion تعمل display links في NSH بتردد 120 Hz للشاشة (التطبيقات التي يبنيها
`nsh package` ومضيف التطوير تطلب ذلك عبر `CADisableMinimumFrameDurationOnPhone`). المراحل هي *tick* (الحركات
الأصلية) و*drain* (تطبيق دفعات المحرّك) و*scroll* (ما يتبع عرض التمرير: القوائم، والخلايا اللاصقة،
والقيم المرتبطة).

<div class="data-table">

| الصفحة | مصدر الإطارات | FPS | زمن الإطار p95 | CPU |
|---|---|---|---|---|
| Home, scrolling | تمرير | 60 | 0.1 ms | 6% |
| Stocks | بيانات حية، حلقات أصلية | 60 | 0.3 ms | 22% |
| Stocks, scrolling | بيانات حية، تمرير | 60 | 0.3 ms | 25% |
| Photos, scrolling | تمرير | 60 | 1.2 ms | 6% |
| Lists, scrolling | تمرير | 60 | 1.1 ms | 8% |
| Scrolling, scrolling | تمرير | 60 | 0.1 ms | 7% |
| Navigation, scrolling | تمرير | 60 | 0.2 ms | 7% |
| Form, scrolling | تمرير | 60 | 0.3 ms | 7% |
| Gestures | springs، حلقة نابضة | 60 | 0.3 ms | 3% |
| Animations | حلقات أصلية | 60 | 0.7 ms | 6% |
| Canvas | حلقات أصلية | 60 | 0.4 ms | 16% |
| Styles | تحويل متمايل | 60 | 0.4 ms | 4% |
| Tailwind, scrolling | تمرير | 60 | 0.2 ms | 7% |
| Text, scrolling | تمرير | 60 | 0.1 ms | 7% |
| Text View, scrolling | تمرير | 60 | 0.1 ms | 6% |
| Images, scrolling | تمرير | 60 | 0.1 ms | 5% |
| Components, scrolling | تمرير | 60 | 0.2 ms | 6% |
| Overlays, scrolling | تمرير | 60 | 0.1 ms | 6% |
| Menus, scrolling | تمرير | 60 | 0.2 ms | 7% |
| Controls, scrolling | تمرير، انتقالات | 60 | 0.2 ms | 5% |
| Web and video, scrolling | تمرير | 60 | 0.1 ms | 8% |
| System | `requestAnimationFrame`، مؤقتات | 60 | 0.3 ms | 4% |
| Standard APIs, scrolling | تمرير | 60 | 0.1 ms | 7% |
| Storage, scrolling | تمرير | 60 | 0.1 ms | 8% |

</div>

*FPS* هو المعدّل أثناء وجود حركة، كما سبق: عند 60 للمحاكي، يأتي كل إطار بعد تحديث واحد من
سابقه. كل صفحة لا يتحرك فيها شيء لا ترسم أي إطار وتستهلك 1–2% من CPU في حالة السكون. تشغل العملية 40 MB في
الصفحة الرئيسية للمعرض ونحو 180 MB بعد الجولة كاملة (صور مخزّنة مؤقتًا عن قصد، ومستندات صفحة Text View).

على iPhone 17 Pro (ProMotion، 120 Hz)، مع مضيف التطوير وعرض توضيحي واحد على الشاشة، ترسم الصفحات المتحركة
في كل تحديث:

<div class="data-table">

| الصفحة | مصدر الإطارات | FPS | زمن الإطار p95 | تجاوز تحديث واحد | CPU | الذاكرة |
|---|---|---|---|---|---|---|
| Stocks | بيانات حية، حلقات أصلية | 120 | 0.2–0.3 ms | 0% | 46–70% | 41–43 MB |
| Canvas | حلقات أصلية | 120 | 0.1 ms | 0% | 25–36% | 37–38 MB |
| Animations | حلقات أصلية | 120 | 0.2 ms | 0% | 3–11% | 37 MB |

</div>

ينفّذ Stocks 20 عملية commit في الثانية (نبضة كل 50 ms)، تستغرق كل منها 1.5 ms في JS و1.4 ms في النواة على خيط
المحرّك (p95 هو 2.2 و2.0 ms)، ويكون هذا الخيط مشغولًا بنسبة 4–6% من الوقت.

<a id="measuring-an-app"></a>

## قياس تطبيق

لقياس تطبيق بالطريقة نفسها، شغّل اختباراته أو خطواته باستخدام `--fps` و`-v` على `--target linux` أو `macos` أو `windows` أو `ios`:

```sh
cargo build --release -p nsh-cli
python3 examples/gallery/tools/perf.py --target macos --only Stocks,Canvas   # the gallery, page by page
echo 'await app.wait(5000)' | nsh -v test App.tsx --target linux --fps        # any app
```
