diff --git a/docs/document/Articles/docs/Integrating Cygwin with VSCode.md b/docs/document/Articles/docs/Integrating Cygwin with VSCode.md
new file mode 100644
index 00000000..3171ed90
--- /dev/null
+++ b/docs/document/Articles/docs/Integrating Cygwin with VSCode.md
@@ -0,0 +1,66 @@
+# Integrating Cygwin with VSCode in Windows
+
+## Installation
+
+Follow guide from [Cygwin](https://cygwin.com/).
+
+## Add terminal profile in `settings.json`
+
+Add new profile for cygwin, this will register a new option when we choose to launch a new integrated terminal.
+
+```json{15, 19}
+{
+ "terminal.integrated.profiles.windows": {
+ "PowerShell": {
+ "source": "PowerShell",
+ "icon": "terminal-powershell"
+ },
+ "Command Prompt": {
+ "path": ["${env:windir}\\Sysnative\\cmd.exe", "${env:windir}\\System32\\cmd.exe"],
+ "args": [],
+ "icon": "terminal-cmd"
+ },
+ "Git Bash": {
+ "source": "Git Bash"
+ },
+ "Cygwin": {
+ "path": "C:\\cygwin64\\bin\\bash.exe",
+ "args": ["--login"],
+ "overrideName": true
+ }
+ },
+}
+```
+
+Then we got a new option to create a integrated terminal.
+![cygwin-option](../pics/cygwin-profile.png)
+
+:::info
+For more information: [Terminal Profiles](https://code.visualstudio.com/docs/terminal/profiles#_cygwin).
+:::
+
+## Change default working directory of cygwin in `.bashrc`
+
+The default working directory of cygwin is `{installation-path}\home\{username}` like `C:\cygwin64\home\anon`.
+
+You might like to launch cygwin with working directory as the root of current user.
+
+- Open cygwin, make sure you're at `~`
+
+```bash
+cd ~
+```
+
+- Execute this line into `.bashrc`.
+
+```bash
+touch .bashrc && echo 'cd /cygdrive/c/users/{username}' >> .bashrc
+```
+
+- Check the content is successfully appended.
+
+```bash
+cat .bashrc
+```
+
+- Launch a new cygwin instance, it will start at your user root.
diff --git a/docs/document/Articles/pics/cygwin-profile.png b/docs/document/Articles/pics/cygwin-profile.png
new file mode 100644
index 00000000..530abc03
Binary files /dev/null and b/docs/document/Articles/pics/cygwin-profile.png differ
diff --git a/docs/document/CesiumJS/docs/1. Init your cesium project with vite.md b/docs/document/CesiumJS/docs/1. Init your cesium project with vite.md
new file mode 100644
index 00000000..a5f36e3f
--- /dev/null
+++ b/docs/document/CesiumJS/docs/1. Init your cesium project with vite.md
@@ -0,0 +1,72 @@
+# Init your cesium project with vite
+
+## Create a latest vue3 project
+
+Redirect to your working directory, run
+
+```bash
+pnpm create vue@latest
+```
+
+Follow the instruction, select options based on your need.(It's recommended to work with `typescript`, `vite` and `Vue Router`)
+
+:::info
+For more information: [Vue3 Tooling](https://vuejs.org/guide/scaling-up/tooling.html#project-scaffolding)
+:::
+
+## Add [cesium vite plugin](/~https://github.com/s3xysteak/vite-plugin-cesium-build)
+
+```bash
+pnpm add -D vite-plugin-cesium-build
+```
+
+```ts{9}
+import { fileURLToPath, URL } from 'node:url';
+import { defineConfig } from 'vite';
+import vue from '@vitejs/plugin-vue';
+import vueJsx from '@vitejs/plugin-vue-jsx';
+import cesium from 'vite-plugin-cesium-build';
+
+// https://vitejs.dev/config/
+export default defineConfig({
+ plugins: [vue(), vueJsx(), cesium()],
+ resolve: {
+ alias: {
+ '@': fileURLToPath(new URL('./src', import.meta.url))
+ }
+ }
+});
+```
+
+## Add a earth at `App.vue`
+
+Delete auto-generated template, add following code.
+
+```vue
+
+
+
+
+
+
+
+```
+
+Start the server.
+
+```bash
+pnpm dev
+```
+
+:::warning
+Check scripts in `package.json` to make sure you use the right command, auto-generated scripts might differ from versions.
+:::
diff --git a/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/CSharpDesignPatternsDemo.csproj b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/CSharpDesignPatternsDemo.csproj
index ad9fcfe2..e769a424 100644
--- a/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/CSharpDesignPatternsDemo.csproj
+++ b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/CSharpDesignPatternsDemo.csproj
@@ -6,9 +6,11 @@
enable
enable
preview
+ Release
+
diff --git a/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Program.cs b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Program.cs
index 45ca91e6..956e127a 100644
--- a/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Program.cs
+++ b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Program.cs
@@ -2,27 +2,96 @@
using CSharpDesignPatternsDemo.Structural;
using CSharpDesignPatternsDemo.Creational;
using System.Numerics;
+using System.Text.Json;
+using BenchmarkDotNet.Attributes;
+using BenchmarkDotNet.Running;
+using BenchmarkDotNet.Configs;
+using BenchmarkDotNet.Validators;
+using BenchmarkDotNet.Loggers;
+using BenchmarkDotNet.Columns;
-var p1 = 20 + 30.Percentage();
-var p2 = 2 - 50f.Percentage();
-var p3 = 4 * 25d.Percentage();
-var p4 = 1 / 66m.Percentage();
-var p11 = 30.Percentage() + 20;
-var p12 = 2f.Percentage() - 50;
-var p13 = 4d.Percentage() * 25;
-var p14 = 1m.Percentage() / 66;
-Print(p1, p2, p3, p4, p11, p12, p13, p14);
+// var enemyCollection = EnemyCollection.Create(10, () => (Random.Shared.Next(18, 36), Random.Shared.NextDouble()));
+// Magic.Freeze(enemyCollection);
+// enemyCollection[2].Agility = 250;
+// Console.WriteLine(enemyCollection._agility![2]);
+// var enemies = new EnemySpan(5, () => (1, 2));
+// foreach (ref var e in enemies.Agility)
+// {
+// e = 250;
+// }
+// foreach (var e in enemies._agility!)
+// {
+// Console.WriteLine(e);
+// }
-static void Print(params object[] objects)
-{
- objects.ToList().ForEach(Console.WriteLine);
-}
+var config = new ManualConfig()
+ .WithOptions(ConfigOptions.DisableOptimizationsValidator)
+ .AddValidator(JitOptimizationsValidator.DontFailOnError)
+ .AddLogger(ConsoleLogger.Default)
+ .AddColumnProvider(DefaultColumnProviders.Instance);
+
+BenchmarkRunner.Run(config);
-Span span = Enumerable.Range(1, 100).ToArray().AsSpan();
-Random.Shared.Shuffle(span);
-var condition = span is [var first, _, .. var _]; // always true
-condition.Out();
-static class OutExtension
+[MemoryDiagnoser]
+public class AoS_SoA
{
- public static void Out(this object o) => Console.WriteLine(o);
-}
\ No newline at end of file
+ private Enemy[]? _aos;
+ private EnemyCollection? _soa;
+ private EnemyCollection2 _soaS;
+
+ private EnemySpan _soaSpan;
+ [Params(10000)] public int _size;
+
+ [GlobalSetup]
+ public void SetUp()
+ {
+ _aos = Enumerable.Range(1, _size)
+ .Select(x => new Enemy() { Age = Random.Shared.Next(18, 36), Agility = Random.Shared.NextDouble() })
+ .ToArray();
+ _soa = EnemyCollection.Create(_size, () => (Random.Shared.Next(18, 36), Random.Shared.NextDouble()));
+ _soaS = EnemyCollection2.Create(_size, () => (Random.Shared.Next(18, 36), Random.Shared.NextDouble()));
+ _soaSpan = new(_size, () => (Random.Shared.Next(18, 36), Random.Shared.NextDouble()));
+ }
+ [Benchmark]
+ public void Freeze_AoS()
+ {
+ for (int i = 0; i < _aos!.Length; i++)
+ {
+ ref Enemy e = ref _aos![i];
+ e.Agility = 0;
+ }
+ }
+ [Benchmark]
+ public void Freeze_SoA()
+ {
+ foreach (var e in _soa!)
+ {
+ e.Agility = 0;
+ }
+ }
+ [Benchmark]
+ public void Freeze_SoA_Enumerator()
+ {
+ var e = _soa!._agility!.GetEnumerator2();
+ while (e.MoveNext())
+ {
+ e.Current = 0;
+ }
+ }
+ [Benchmark]
+ public void Freeze_SoA_Struct()
+ {
+ foreach (var e in _soaS)
+ {
+ e.Agility = 0;
+ }
+ }
+ [Benchmark]
+ public void Freeze_SoA_Span()
+ {
+ foreach (ref var e in _soaSpan.Agility)
+ {
+ e = 0;
+ }
+ }
+}
diff --git a/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Structural/5. Proxy/4. Composite Proxy - AoS and SoA.cs b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Structural/5. Proxy/4. Composite Proxy - AoS and SoA.cs
new file mode 100644
index 00000000..144d85d7
--- /dev/null
+++ b/docs/document/Csharp Design Patterns/CsharpDesignPatternsDemo/Structural/5. Proxy/4. Composite Proxy - AoS and SoA.cs
@@ -0,0 +1,245 @@
+using System.Collections;
+using System.Runtime.CompilerServices;
+using Microsoft.Diagnostics.Tracing;
+
+namespace CSharpDesignPatternsDemo.Structural;
+
+struct Enemy
+{
+ public int Age { get; set; }
+ public double Agility { get; set; }
+}
+
+class EnemyCollection(int size)
+{
+ internal int[]? _age;
+ internal double[]? _agility;
+ private readonly int _size = size;
+ public EnemyShadow this[int index] => new(this, index);
+ public static EnemyCollection Create(int size, Func<(int age, double agility)>? generator = default)
+ {
+ var result = new EnemyCollection(size)
+ {
+ _age = new int[size],
+ _agility = new double[size]
+ };
+ if (generator is { })
+ {
+ for (int i = 0; i < size; i++)
+ (result._age[i], result._agility[i]) = generator();
+ }
+ return result;
+ }
+
+ public ref struct Enumerator
+ {
+ private readonly EnemyCollection _enemies;
+ private int _index;
+ public Enumerator(EnemyCollection enemy)
+ {
+ _enemies = enemy;
+ _index = -1;
+ }
+ public readonly EnemyShadow Current => _enemies[_index];
+
+ public bool MoveNext()
+ {
+ int index = _index + 1;
+ if (index < _enemies._size)
+ {
+ _index = index;
+ return true;
+ }
+ return false;
+ }
+ }
+ public Enumerator GetEnumerator() => new(this);
+}
+
+readonly ref struct EnemyShadow
+{
+ private readonly int _index;
+ private readonly EnemyCollection _enemies;
+ public EnemyShadow(EnemyCollection enemies, int index) => (_enemies, _index) = (enemies, index);
+ public ref int Age => ref _enemies._age![_index];
+ public ref double Agility => ref _enemies._agility![_index];
+}
+static class Magic
+{
+ public struct ArrayEnumerator
+ {
+ T[] _arr;
+ int _index;
+ public ref T Current => ref _arr[_index];
+ public ArrayEnumerator(in T[] arr)
+ {
+ _arr = arr;
+ _index = -1;
+ }
+ public bool MoveNext()
+ {
+ int index = _index + 1;
+ if (index < _arr.Length)
+ {
+ _index = index;
+ return true;
+ }
+ return false;
+ }
+ }
+ public static ArrayEnumerator GetEnumerator2(this T[] arr)
+ {
+ return new(in arr);
+ }
+ // public static void Freeze(Enemy[] enemies)
+ // {
+ // foreach (var e in enemies) e.Agility = 0;
+ // }
+
+ // public static void Freeze(IEnumerable enemies)
+ // {
+ // foreach (var e in enemies) e.Agility = 0;
+ // }
+ public static void Freeze(EnemyCollection enemies)
+ {
+ foreach (var e in enemies) e.Agility = 0;
+ }
+ public static void Age(EnemyCollection enemies, int count = 1)
+ {
+ foreach (var e in enemies) e.Age += count;
+ }
+ // public static void Age(Enemy[] enemies, int count = 1)
+ // {
+ // foreach (var e in enemies) e.Age += count;
+ // }
+}
+
+
+struct EnemyCollection2(int size)
+{
+ internal int[]? _age;
+ internal double[]? _agility;
+ private readonly int _size = size;
+ public EnemyShadow2 this[int index] => new(this, index);
+ public static EnemyCollection2 Create(int size, Func<(int age, double agility)>? generator = default)
+ {
+ var result = new EnemyCollection2(size)
+ {
+ _age = new int[size],
+ _agility = new double[size]
+ };
+ if (generator is { })
+ {
+ for (int i = 0; i < size; i++)
+ (result._age[i], result._agility[i]) = generator();
+ }
+ return result;
+ }
+
+ public ref struct Enumerator
+ {
+ private readonly EnemyCollection2 _enemies;
+ private int _index;
+ public Enumerator(EnemyCollection2 enemy)
+ {
+ _enemies = enemy;
+ _index = -1;
+ }
+ public readonly EnemyShadow2 Current => _enemies[_index];
+
+ public bool MoveNext()
+ {
+ int index = _index + 1;
+ if (index < _enemies._size)
+ {
+ _index = index;
+ return true;
+ }
+ return false;
+ }
+
+ }
+ public Enumerator GetEnumerator() => new(this);
+}
+readonly ref struct EnemyShadow2
+{
+ private readonly int _index;
+ private readonly EnemyCollection2 _enemies;
+ public EnemyShadow2(EnemyCollection2 enemies, int index) => (_enemies, _index) = (enemies, index);
+ public ref int Age => ref _enemies._age![_index];
+ public ref double Agility => ref _enemies._agility![_index];
+}
+
+struct EnemySpan(int size)
+{
+ internal int[]? _age = new int[size];
+ internal double[]? _agility = new double[size];
+ internal readonly Span Age => _age.AsSpan();
+ internal readonly Span Agility => _agility.AsSpan();
+ int _size = size;
+
+ public EnemySpan(int size, Func<(int age, double agility)>? generator = default) : this(size)
+ {
+ if (generator is { })
+ {
+ for (int i = 0; i < size; i++)
+ (_age![i], _agility![i]) = generator();
+ }
+ }
+ public Enumerator GetEnumerator() => new(this);
+ public ref struct Enumerator
+ {
+ private EnemySpan _enemies;
+ private int _index;
+ public Enumerator(EnemySpan enemy)
+ {
+ _enemies = enemy;
+ _index = -1;
+ }
+ public EnemyShadow3 Current => new(ref _enemies.Age[_index], ref _enemies.Agility[_index]);
+
+ public bool MoveNext()
+ {
+ int index = _index + 1;
+ if (index < _enemies._size)
+ {
+ _index = index;
+ return true;
+ }
+ return false;
+ }
+ }
+}
+ref struct EnemyShadow3
+{
+ private static readonly int[] a = { 1 };
+ private static readonly double[] b = { 1 };
+
+ private readonly int _index;
+ private readonly EnemySpan _enemies;
+ public EnemyShadow3(ref EnemySpan enemies, int index) => (_enemies, _index) = (enemies, index);
+ public EnemyShadow3(ref int age, ref double agility)
+ {
+ _age = age;
+ _agility = agility;
+ }
+ private ref int _age = ref a[0];
+ private ref double _agility = ref b[0];
+ public ref int Age
+ {
+ get
+ {
+ // if (!_enemies.Equals(default)) return ref _enemies.Age[_index];
+ return ref _age;
+ }
+ }
+
+ public ref double Agility
+ {
+ get
+ {
+ // if (!_enemies.Equals(default)) return ref _enemies.Agility[_index];
+ return ref _agility;
+ }
+ }
+}
\ No newline at end of file
diff --git a/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md b/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md
index ae422665..ef6e7e4e 100644
--- a/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md
+++ b/docs/document/Csharp Design Patterns/docs/Structural/6. Proxy.md
@@ -221,3 +221,47 @@ static class PercentageExtension
}
}
```
+
+## Composite Proxy - `Aos/SoA`
+
+In some scenarios we do enumerations to modify values of a collection of certain structured type.
+Assuming we are developing a game, `Enemy` is an entity model and we can perform magic on an collection of them.
+
+An array of entity model `Entity` can be called as `Array of Structure(AoS)`.
+
+```cs
+var enemies = Enumerable.Range(1, 100)
+ .Select(_ => new Enemy() { Age = Random.Shared.Next(18, 36), Agility = Random.Shared.NextDouble() })
+ .ToArray();
+
+Magic.Freeze(enemies);
+
+class Enemy
+{
+ public int Age { get; set; }
+ public double Agility { get; set; }
+}
+
+static class Magic
+{
+ public static void Freeze(params Enemy[] enemies)
+ {
+ foreach (var e in enemies) e.Agility = 0;
+ }
+
+ public static void Freeze(IEnumerable enemies)
+ {
+ foreach (var e in enemies) e.Agility = 0;
+ }
+}
+```
+
+### Problem of `AoS`
+
+When iterating over a field of all elements (e.g., updating all `Agility`), the memory access pattern can be non-contiguous, leading to cache misses and reduced performance.
+
+### Solution - `SoA`
+
+```cs
+
+```
diff --git a/docs/document/Vue3/docs/1. Create a latest vue project/1. Start with vue3 and vite.md b/docs/document/Vue3/docs/1. Create a latest vue project/1. Start with vue3 and vite.md
new file mode 100644
index 00000000..cca38163
--- /dev/null
+++ b/docs/document/Vue3/docs/1. Create a latest vue project/1. Start with vue3 and vite.md
@@ -0,0 +1,15 @@
+# Start with vue3 and vite
+
+## Create a new project
+
+Redirect to your working directory, run
+
+```bash
+npm create vue@latest
+```
+
+Follow the instruction, select options based on your need.(It's recommended to work with `typescript`, `vite` and `Vue Router`)
+
+:::info
+For more information: [Vue3 Tooling](https://vuejs.org/guide/scaling-up/tooling.html#project-scaffolding)
+:::
diff --git a/docs/document/Vue3/docs/1. Create a latest vue project/2. Project structure.md b/docs/document/Vue3/docs/1. Create a latest vue project/2. Project structure.md
new file mode 100644
index 00000000..691ab054
--- /dev/null
+++ b/docs/document/Vue3/docs/1. Create a latest vue project/2. Project structure.md
@@ -0,0 +1,15 @@
+# Project structure
+
+## Folder
+
+### First level
+
+- `public` stores static resources to be packed when building. Files in it can be things like an icon.
+- `src` stores components, scripts, css, tests, routing configs, and more.
+
+```txt
+.
+├── node_modules
+├── public
+└── src
+```
diff --git a/docs/document/Vue3/docs/1. Define a Component and Reuse it/1. How to define a component.md b/docs/document/Vue3/docs/2. Define a Component and Reuse it/1. How to define a component.md
similarity index 100%
rename from docs/document/Vue3/docs/1. Define a Component and Reuse it/1. How to define a component.md
rename to docs/document/Vue3/docs/2. Define a Component and Reuse it/1. How to define a component.md
diff --git a/docs/document/Vue3/docs/1. Define a Component and Reuse it/2. Bring component into scope.md b/docs/document/Vue3/docs/2. Define a Component and Reuse it/2. Bring component into scope.md
similarity index 100%
rename from docs/document/Vue3/docs/1. Define a Component and Reuse it/2. Bring component into scope.md
rename to docs/document/Vue3/docs/2. Define a Component and Reuse it/2. Bring component into scope.md
diff --git a/docs/document/Vue3/docs/2. Define a Component and Reuse it/3. Reference an DOM.md b/docs/document/Vue3/docs/2. Define a Component and Reuse it/3. Reference an DOM.md
new file mode 100644
index 00000000..36dd3a9f
--- /dev/null
+++ b/docs/document/Vue3/docs/2. Define a Component and Reuse it/3. Reference an DOM.md
@@ -0,0 +1,3 @@
+# Reference an DOM
+
+## `ref`
diff --git a/docs/document/Vue3/docs/2. Lifecycle/1. Component Lifecycle.md b/docs/document/Vue3/docs/3. Lifecycle/1. Component Lifecycle.md
similarity index 100%
rename from docs/document/Vue3/docs/2. Lifecycle/1. Component Lifecycle.md
rename to docs/document/Vue3/docs/3. Lifecycle/1. Component Lifecycle.md