Skip to content

Commit

Permalink
Update Document for v1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
liiir1985 committed Sep 26, 2017
1 parent 43c1c02 commit b6e7a50
Show file tree
Hide file tree
Showing 21 changed files with 48 additions and 33 deletions.
2 changes: 2 additions & 0 deletions ReadMe.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,6 @@ ILRuntime

[中文在线文档](https://ourpalm.github.io/ILRuntime/)

[Unity Demo Project, Unity示例工程](https://ourpalm.github.io/ILRuntimeU3D/)

QQ群:512079820
2 changes: 1 addition & 1 deletion docs/public/readme.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
4 changes: 2 additions & 2 deletions docs/public/v1/guide/bind.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down Expand Up @@ -166,7 +166,7 @@ <h2 id="CLR绑定"><a href="#CLR绑定" class="headerlink" title="CLR绑定"></a
<p>但是这种方式有着明显的弊端,最突出的一点就是通过反射来调用接口调用效率会比直接调用低很多,再加上反射传递函数参数时需要使用<code>object[]</code>数组,这样不可避免的每次调用都会产生不少GC Alloc。众所周知GC Alloc高意味着在Unity中执行会存在较大的性能问题。</p>
<p>ILRuntime通过CLR方法绑定机制,可以<code>选择性</code>的对经常使用的CLR接口进行直接调用,从而尽可能的消除反射调用开销以及额外的<code>GC Alloc</code></p>
<h3 id="使用方法"><a href="#使用方法" class="headerlink" title="使用方法"></a>使用方法</h3><p>CLR绑定借助了ILRuntime的CLR重定向机制来实现,因为实质上也是将对CLR方法的反射调用重定向到我们自己定义的方法里面来。但是手动编写CLR重定向方法是个工作量非常巨大的事,而且要求对ILRuntime底层机制非常了解(比如如何装拆箱基础类型,怎么处理Ref/Out引用等等),因此ILRuntime提供了一个代码生成工具来自动生成CLR绑定代码。</p>
<p>CLR绑定代码的自动生成工具使用方法如下:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line">[<span class="meta">MenuItem(<span class="meta-string">"ILRuntime/Generate CLR Binding Code"</span>)</span>]</div><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">GenerateCLRBinding</span>(<span class="params"></span>)</span></div><div class="line">&#123;</div><div class="line"> List&lt;Type&gt; types = <span class="keyword">new</span> List&lt;Type&gt;();</div><div class="line"> <span class="comment">//在List中添加你想进行CLR绑定的类型</span></div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">int</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">float</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">long</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">object</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">string</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Console));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Array));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Dictionary&lt;<span class="keyword">string</span>, <span class="keyword">int</span>&gt;));</div><div class="line"> <span class="comment">//所有ILRuntime中的类型,实际上在C#运行时中都是ILRuntime.Runtime.Intepreter.ILTypeInstance的实例,</span></div><div class="line"> <span class="comment">//因此List&lt;A&gt; List&lt;B&gt;,如果A与B都是ILRuntime中的类型,只需要添加List&lt;ILRuntime.Runtime.Intepreter.ILTypeInstance&gt;即可</span></div><div class="line"> types.Add(<span class="keyword">typeof</span>(Dictionary&lt;ILRuntime.Runtime.Intepreter.ILTypeInstance, <span class="keyword">int</span>&gt;));</div><div class="line"> <span class="comment">//第二个参数为自动生成的代码保存在何处</span></div><div class="line"> ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(types, <span class="string">"Assets/ILRuntime/Generated"</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>CLR绑定代码的自动生成工具使用方法如下:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line">[<span class="meta">MenuItem(<span class="meta-string">"ILRuntime/Generate CLR Binding Code"</span>)</span>]</div><div class="line"><span class="function"><span class="keyword">static</span> <span class="keyword">void</span> <span class="title">GenerateCLRBinding</span>(<span class="params"></span>)</span></div><div class="line"><span class="function"></span>&#123;</div><div class="line"> List&lt;Type&gt; types = <span class="keyword">new</span> List&lt;Type&gt;();</div><div class="line"> <span class="comment">//在List中添加你想进行CLR绑定的类型</span></div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">int</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">float</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">long</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">object</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(<span class="keyword">string</span>));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Console));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Array));</div><div class="line"> types.Add(<span class="keyword">typeof</span>(Dictionary&lt;<span class="keyword">string</span>, <span class="keyword">int</span>&gt;));</div><div class="line"> <span class="comment">//所有ILRuntime中的类型,实际上在C#运行时中都是ILRuntime.Runtime.Intepreter.ILTypeInstance的实例,</span></div><div class="line"> <span class="comment">//因此List&lt;A&gt; List&lt;B&gt;,如果A与B都是ILRuntime中的类型,只需要添加List&lt;ILRuntime.Runtime.Intepreter.ILTypeInstance&gt;即可</span></div><div class="line"> types.Add(<span class="keyword">typeof</span>(Dictionary&lt;ILRuntime.Runtime.Intepreter.ILTypeInstance, <span class="keyword">int</span>&gt;));</div><div class="line"> <span class="comment">//第二个参数为自动生成的代码保存在何处</span></div><div class="line"> ILRuntime.Runtime.CLRBinding.BindingCodeGenerator.GenerateBindingCode(types, <span class="string">"Assets/ILRuntime/Generated"</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>在CLR绑定代码生成之后,需要将这些绑定代码注册到AppDomain中才能使CLR绑定生效,但是一定要记得将CLR绑定的注册写在CLR重定向的注册后面,因为同一个方法只能被重定向一次,只有先注册的那个才能生效。</p>
<p>注册方法如下:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line">ILRuntime.Runtime.Generated.CLRBindings.Initialize(appdomain);</div></pre></td></tr></table></figure></p>

Expand Down
2 changes: 1 addition & 1 deletion docs/public/v1/guide/contribution.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
5 changes: 3 additions & 2 deletions docs/public/v1/guide/cross-domain.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/public/v1/guide/delegate.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
2 changes: 1 addition & 1 deletion docs/public/v1/guide/il2cpp.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
2 changes: 1 addition & 1 deletion docs/public/v1/guide/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
2 changes: 1 addition & 1 deletion docs/public/v1/guide/litjson.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
8 changes: 4 additions & 4 deletions docs/public/v1/guide/performance-optimization.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down Expand Up @@ -171,10 +171,10 @@ <h3 id="CLR绑定"><a href="#CLR绑定" class="headerlink" title="CLR绑定"></a
<blockquote>
<p>在Unity的示例工程中,有关于CLR绑定使用的例子,<br>通过ILRuntime菜单里的Generate CLRBinding code选项可以自动生成所需要的绑定代码</p>
</blockquote>
<h3 id="值类型"><a href="#值类型" class="headerlink" title="值类型"></a>值类型</h3><p>由于值类型的特殊和ILRuntime的实现原理,目前没有办法做到直接在栈上为所有类型申请内存,因此依然只有将值类型进行装箱,然后在通过深层拷贝来模拟值类型的行为</p>
<p>因此在ILRuntime中值类型的运行效率会低于引用类型,并且在赋值时可能还会产生额外的GC Alloc,因此在热更DLL当中应该尽量避免大量使用值类型</p>
<h3 id="值类型"><a href="#值类型" class="headerlink" title="值类型"></a>值类型</h3><p>由于值类型的特殊和ILRuntime的实现原理,使用ILRuntime外部定义的值类型(例如UnityEngine.Vector3)在默认情况下会造成额外的装箱拆箱开销,以及相对应的GC Alloc内存分配</p>
<p>为了解决这个问题,ILRuntime在1.3.0版中增加了值类型绑定(ValueTypeBinding)机制,通过对这些值类型添加绑定器,可以大幅增加值类型的执行效率,以及避免GC Alloc内存分配。具体用法请参考ILRuntime的Unity3D示例工程或者ILRuntime的TestCases测试用例工程。</p>
<h3 id="接口调用建议"><a href="#接口调用建议" class="headerlink" title="接口调用建议"></a>接口调用建议</h3><p>为了调用方便,ILRuntime的很多接口使用了params可变参数,但是有可能会无意间忽视这个操作带来的GCAlloc,例如下面的操作:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line">appdomain.Invoke(<span class="string">"MyGame.Main"</span>, <span class="string">"Initialize"</span>, <span class="literal">null</span>);</div><div class="line">appdomain.Invoke(<span class="string">"MyGame.Main"</span>, <span class="string">"Start"</span>, <span class="literal">null</span>, <span class="number">100</span>, <span class="number">200</span>);</div></pre></td></tr></table></figure></p>
<p>这两个操作在调用的时候,会分别生成一个<code>object[0]</code><code>object[2]</code>,从而产生GC Alloc,这一点很容易被忽略。所以如果你需要在Update等性能关键的地方调用热更DLL中的方法,应该按照以下方式缓存这个参数数组:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line"><span class="keyword">object</span>[] param0 = <span class="keyword">new</span> <span class="keyword">object</span>[<span class="number">0</span>];</div><div class="line"><span class="keyword">object</span>[] param2 = <span class="keyword">new</span> <span class="keyword">object</span>[<span class="number">2</span>];</div><div class="line">IMethod m, m2;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">Start</span>(<span class="params"></span>)</span></div><div class="line">&#123;</div><div class="line"> m = appdomain.LoadedTypes[<span class="string">"MyGame.SomeUI"</span>].GetMethod(<span class="string">"Update"</span>, <span class="number">0</span>);</div><div class="line"> m2 = appdomain.LoadedTypes[<span class="string">"MyGame.SomeUI"</span>].GetMethod(<span class="string">"SomethingAfterUpdate"</span>, <span class="number">2</span>);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">Update</span>(<span class="params"></span>)</span></div><div class="line">&#123;</div><div class="line"> appdomain.Invoke(m, <span class="literal">null</span>, param0);</div><div class="line"> param2[<span class="number">0</span>] = <span class="keyword">this</span>;</div><div class="line"> param2[<span class="number">1</span>] = appdomain;</div><div class="line"> appdomain.Invoke(m2, <span class="literal">null</span>, param2);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>这两个操作在调用的时候,会分别生成一个<code>object[0]</code><code>object[2]</code>,从而产生GC Alloc,这一点很容易被忽略。所以如果你需要在Update等性能关键的地方调用热更DLL中的方法,应该按照以下方式缓存这个参数数组:<br><figure class="highlight csharp"><table><tr><td class="code"><pre><div class="line"><span class="keyword">object</span>[] param0 = <span class="keyword">new</span> <span class="keyword">object</span>[<span class="number">0</span>];</div><div class="line"><span class="keyword">object</span>[] param2 = <span class="keyword">new</span> <span class="keyword">object</span>[<span class="number">2</span>];</div><div class="line">IMethod m, m2;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">Start</span>(<span class="params"></span>)</span></div><div class="line"><span class="function"></span>&#123;</div><div class="line"> m = appdomain.LoadedTypes[<span class="string">"MyGame.SomeUI"</span>].GetMethod(<span class="string">"Update"</span>, <span class="number">0</span>);</div><div class="line"> m2 = appdomain.LoadedTypes[<span class="string">"MyGame.SomeUI"</span>].GetMethod(<span class="string">"SomethingAfterUpdate"</span>, <span class="number">2</span>);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">Update</span>(<span class="params"></span>)</span></div><div class="line"><span class="function"></span>&#123;</div><div class="line"> appdomain.Invoke(m, <span class="literal">null</span>, param0);</div><div class="line"> param2[<span class="number">0</span>] = <span class="keyword">this</span>;</div><div class="line"> param2[<span class="number">1</span>] = appdomain;</div><div class="line"> appdomain.Invoke(m2, <span class="literal">null</span>, param2);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>通过缓存IMethod实例以及参数列表数组,可以做到这个Update操作不会产生任何额外的GC Alloc,并且以最高的性能来执行</p>

<div class="footer">
Expand Down
2 changes: 1 addition & 1 deletion docs/public/v1/guide/principle.html
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
<nav class="nav">
<div class="border">
<img src="/ILRuntime/public/images/logo.png" />
<button class="hiden-in-phone">V1.2</button>
<button class="hiden-in-phone">V1.3</button>
<button id="btn-menu" class="hiden-in-pc">菜单</button>
<ul class="nav-link hiden-in-phone">
<!--li>
Expand Down
Loading

0 comments on commit b6e7a50

Please sign in to comment.