1 |
#Region "Microsoft.VisualBasic::fbae67b2a610cf873dc16ac6a28a5169, Microsoft.VisualBasic.Core\ApplicationServices\VBDev\Ngen\Ngen.vb"
|
2 |
|
3 |
|
4 |
|
5 |
|
6 |
|
7 |
|
8 |
|
9 |
|
10 |
|
11 |
|
12 |
|
13 |
|
14 |
|
15 |
|
16 |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 |
|
25 |
|
26 |
|
27 |
|
28 |
|
29 |
|
30 |
|
31 |
|
32 |
|
33 |
|
34 |
|
35 |
|
36 |
|
37 |
|
38 |
|
39 |
|
40 |
|
41 |
|
42 |
|
43 |
|
44 |
|
45 |
|
46 |
|
47 |
|
48 |
|
49 |
|
50 |
|
51 |
|
52 |
|
53 |
|
54 |
|
55 |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 |
|
66 |
|
67 |
|
68 |
|
69 |
|
70 |
|
71 |
|
72 |
|
73 |
|
74 |
#End Region
|
75 |
|
76 |
Imports System.ComponentModel
|
77 |
Imports System.Runtime.InteropServices
|
78 |
Imports System.Text
|
79 |
Imports Microsoft.VisualBasic.ApplicationServices
|
80 |
Imports Microsoft.VisualBasic.CommandLine
|
81 |
Imports Microsoft.VisualBasic.CommandLine.Reflection
|
82 |
Imports Microsoft.VisualBasic.Language
|
83 |
Imports Microsoft.VisualBasic.Language.UnixBash
|
84 |
|
85 |
Namespace ApplicationServices
|
86 |
|
87 |
|
88 |
|
89 |
|
90 |
The Native Image Generator (Ngen.exe) is a tool that improves the performance of managed applications.
|
91 |
Ngen.exe creates native images, which are files containing compiled processor-specific machine code,
|
92 |
and installs them into the native image cache on the local computer. The runtime can use native images
|
93 |
from the cache instead of using the just-in-time (JIT) compiler to compile the original assembly.
|
94 |
|
95 |
Changes To Ngen.exe In the .NET Framework 4
|
96 |
Ngen.exe now compiles assemblies With full trust, And code access security (CAS) policy Is no longer evaluated.
|
97 |
Native images that are generated With Ngen.exe can no longer be loaded into applications that are running In Partial trust.
|
98 |
|
99 |
Changes To Ngen.exe In the .NET Framework version 2.0:
|
100 |
Installing an assembly also installs its dependencies, simplifying the syntax Of Ngen.exe.
|
101 |
Native images can now be Shared across application domains.
|
102 |
A New Action, update, re - creates images that have been invalidated.
|
103 |
Actions can be deferred For execution by a service that uses idle time On the computer To generate And install images.
|
104 |
Some causes Of image invalidation have been eliminated.
|
105 |
</summary>
|
106 |
<remarks>
|
107 |
1.7 Native代码产生器: NGen.exe
|
108 |
|
109 |
随.NET Framework发布的NGen.exe工具可以将IL代码编译成native代码, 当应用程序安装在用户的机器上时. 因为代码是在安装的时候编译的, CLR的JIT编译器不需要在运行时刻编译IL代码
|
110 |
这能提高应用程序的性能. NGen.exe工具在下面两个场合很有趣:
|
111 |
|
112 |
提高了应用程序的启动速度 运行NGen.exe能提高启动速度, 因为代码已经编译成native代码, 所以在运行时就不需要编译了
|
113 |
减少应用程序的工作集 如果你认为一个程序集会被同时载入到多个进程/ Appdomain, 在这个程序集上运行NGen.exe能减少应用程序的工作集, 其原因是NGen.exe工具将IL编译成native代码,
|
114 |
然后将输出保存到单独的文件中, 这个文件能同时被内存映射(memory - mapping)到多个进程地址空间中, 允许代码共享, 每个进程 / AppDomain不必为自己拷贝一份代码
|
115 |
|
116 |
当一个安装程序调用NGen.exe对一个应用程序或程序集进行编译时, 那个应用程序的所有程序集或者一个特定的程序集会把其IL代码编译成native代码, 一个新的只包含native代码而不含有IL的程序集文件会被NGen.exe创建.
|
117 |
这个新的文件被放到名字类似于 C: /Windows/Assembly/NativeImages_v2.0.50727_32的文件夹下面, 这个文件家名字包含了CLR的版本和native代码是否是为x86(32位版本的Windows), x64,
|
118 |
或者Itaninum(64位版本的Windows)编译的信息.
|
119 |
|
120 |
现在, 当CLR载入一个程序集文件时, CLR查看对应的NGen native文件是否存在, 如果没发现native文件, CLR JIT对IL代码像通常那样进行编译.
|
121 |
然而, 如果对应的native文件存在, CLR将使用native文件中的编译好的代码, 文件中的函数就不需要在运行时刻编译了.
|
122 |
|
123 |
在表面上, 这听起来非常好, 听上去就像如果你得到了托管代码的全部优点(垃圾回收, 代码验证, 类型安全, 等等)而不牺牲托管代码的性能(JIT编译),
|
124 |
但是实际情况并不总是那么美好, NGen
|
125 |
|
126 |
没有知识产权保护 很多人以为可以发布NGen文件而不用发布包含原始IL代码的文件, 从而使他们的知识产权更加保密
|
127 |
不幸的是, 这并不可行, 在运行时刻, CLR需要访问程序集的metadata(为某些函数, 例如反射和串行化函数), 这需要发布包含IL和metadata的程序集.
|
128 |
此外, 如果由于某种原因, CLR不能使用NGen文件(如下面所描述的), 那么CLR会回到JIT编译, 对程序集的IL代码进行编译, 因此IL代码必须存在.
|
129 |
|
130 |
NGen文件可能会过时 当CLR载入NGen文件时, 它会比较以前编译的代码和当前的执行环境的很多特征, 如果任何特征不匹配, NGen文件就不能被使用, JIT编译器进程就要使用. 这是必须被匹配的部分特征列表.
|
131 |
|
132 |
程序集模块的版本ID(MVID)
|
133 |
被引用的程序集的版本ID
|
134 |
处理器类型
|
135 |
CLR版本
|
136 |
Build类型(release, debug, optimized debug, profiling, 等等)
|
137 |
|
138 |
所有链接时的安全性要求都必须在运行时刻被满足才能允许载入.
|
139 |
|
140 |
注意有可能以升级的方式运行NGen.exe, 这告诉工具对以前曾经被执行NGen
|
141 |
那么service pack的安装程序将会在更新模式下自动运行NGen.exe, 使得NGen文件保持和CLR的版本一致.
|
142 |
|
143 |
较差的载入时性能(重定位/绑定): 程序集文件是标准的Windows PE文件, 每个文件包含着一个优先使用的基地址. 很多Windows开发者对围绕基地址和重定位的问题很熟悉,
|
144 |
关于这个主题的更多信息, 可以参考我的书 programming Applications for Microsoft Windows, 4th Edition. 当JIT编译代码时, 不必关心这些问题, 因为正确的内存地址引用会在运行时计算出来.
|
145 |
|
146 |
然而, NGen的程序集文件的一些内存地址引用是静态计算的, 当Windows加载一个NGen文件时, 它检查文件是否被载入到优先的基地址上, 如果文件没有载入到优先的基地址,
|
147 |
Windows会重新定位文件, 修改所有内存地址引用. 这是极其耗时的, 因为Windows必须载入整个文件, 并修改文件中的很多字节. 此外, 这个页面文件对应的代码不能跨进程边界共享.
|
148 |
|
149 |
因此如果你打算NGen程序集文件, 你应该为你的程序集文件选择好的基地址(通过csc.exe的 / baseaddress命令行开关).当你NGen一个程序集文件时, NGen文件将被赋予一个基地址,
|
150 |
这需要使用一个基于托管程序集基地址的算法. 不幸的是, 微软从没有一个良好的指导来帮助开发者如何赋予基地址. 在64位版本的Windows上, 这还不太会成为问题, 因为地址空间是很充足的,
|
151 |
但是对于一个32位的地址空间, 为每一个程序集选择一个好的基地址几乎是不可能的, 除非你精确地知道什么东西会被载入到进程, 知道那个程序集的大小不会超过后一个版本.
|
152 |
|
153 |
较差的执行时性能 当编译代码时, NGen对执行环境做出的假设不会比JIT编译器的多, 这会造成NGen.exe产生较差的代码, 例如, NGen不能优化一些CPU指令, 对静态字段的访问需要简介的操作,
|
154 |
因为静态字段实际的地址需要在运行时刻才能知道.NGen到处插入代码来调用类的构造函数, 因为它不知道代码执行的次序, 不知道类的构造憾事是否已经被调用了(见第8章, 类的构造函数).
|
155 |
一些NGen应用程序会比JIT编译的代码慢大约5%, 因此, 如果你打算使用NGen来提高应用程序的性能, 你应该对比NGen’d和非NGen’d版本的应用程序, 确定NGen’d版本在实际执行时并不慢.
|
156 |
对于一些应用程序, 减小的工作集大小会提高性能, 因此NGen总体上还是会取胜.
|
157 |
|
158 |
因为上面列出的所有问题, 当考虑使用NGen.exe时, 你应该非常小心.对于服务器端的应用程序来说, NGen.exe的用处很小甚至没有意义, 因为只有第一个客户需求经历了性能上的下降,
|
159 |
后面的客户需求都是高速运行的.此外, 对于大多数服务器应用程序, 只需要代码的一个实例, 因此没有工作集方面的利益.
|
160 |
|
161 |
对于客户端应用程序, NGen.exe可能对于提高启动速度或者减小工作集有帮助, 如果程序集被多个应用程序同时使用.甚至没有多个应用程序使用一个程序集, NGen一个程序集也会提高工作集.
|
162 |
此外, 如果NGen.exe被用于所有的客户端应用程序的程序集, 那么CLR就根本不需要载入JIT编译器, 从而更进一步地降低了工作集.
|
163 |
当然, 如果只有一个程序集不是NGen
|
164 |
</remarks>
|
165 |
<RunInstaller(True)>
|
166 |
<[Namespace]("Ngen")>
|
167 |
Public Module NgenInstaller
|
168 |
|
169 |
#Region "Actions::The following table shows the syntax Of Each action."
|
170 |
|
171 |
Public Enum Scenarios
|
172 |
|
173 |
Generate native images that can be used under a debugger.
|
174 |
</summary>
|
175 |
<Description("/Debug")> Debug
|
176 |
|
177 |
Generate native images that can be used under a profiler.
|
178 |
</summary>
|
179 |
<Description("/Profile")> Profile
|
180 |
|
181 |
Generate the minimum number Of native images required by the specified scenario options.
|
182 |
</summary>
|
183 |
<Description("/NoDependencies")> NoDependencies
|
184 |
End Enum
|
185 |
|
186 |
Public Enum PriorityLevels
|
187 |
null = -1
|
188 |
|
189 |
|
190 |
1 Native images are generated And installed immediately, without waiting For idle time.
|
191 |
</summary>
|
192 |
Immediately = 1
|
193 |
|
194 |
2 Native images are generated And installed without waiting For idle time, but after all priority 1 actions (And their dependencies) have completed.
|
195 |
</summary>
|
196 |
Waiting = 2
|
197 |
|
198 |
3 Native images are installed When the native image service detects that the computer Is idle. See Native Image Service.
|
199 |
</summary>
|
200 |
Idle
|
201 |
End Enum
|
202 |
|
203 |
|
204 |
Generate native images for an assembly and its dependencies and install the images in the native image cache.
|
205 |
</summary>
|
206 |
<param name="assemblyName">
|
207 |
The full display name of the assembly. For example, "myAssembly, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0038abc9deabfle5".
|
208 |
Only one assembly can be specified per Ngen.exe command line.
|
209 |
|
210 |
* Note You can supply a Partial assembly name, such As myAssembly, For the display And uninstall actions.
|
211 |
|
212 |
The explicit path of the assembly. You can specify a full or relative path.
|
213 |
If you specify a file name without a path, the assembly must be located In the current directory.
|
214 |
Only one assembly can be specified per Ngen.exe command line.
|
215 |
</param>
|
216 |
<param name="scenarios"></param>
|
217 |
<param name="ExeConfig">exePath, Use the configuration of the specified executable assembly.
|
218 |
Ngen.exe needs to make the same decisions as the loader when binding to dependencies. When a shared component Is loaded at run time,
|
219 |
using the Load method, the application
|
220 |
for example, the version of a dependency that is loaded. The /ExeConfig switch gives Ngen.exe guidance on which dependencies would be loaded at run time.</param>
|
221 |
<param name="AppBase">directoryPath, When locating dependencies, use the specified directory as the application base.</param>
|
222 |
<param name="queue">If /queue is specified, the action is queued for the native image service. The default priority is 3. See the Priority Levels table.</param>
|
223 |
Public Function Install(assemblyName$,
|
224 |
scenarios As NgenInstaller.Scenarios,
|
225 |
Optional ExeConfig$ = "",
|
226 |
Optional AppBase As Boolean = False,
|
227 |
Optional queue As NgenInstaller.PriorityLevels = PriorityLevels.null) As String
|
228 |
|
229 |
Dim cliBuilder As New StringBuilder("install ", 1024)
|
230 |
|
231 |
Call cliBuilder.Append(assemblyName.CLIPath & " ")
|
232 |
Call cliBuilder.Append(scenarios.Description & " ")
|
233 |
|
234 |
If Not String.IsNullOrEmpty(ExeConfig) Then
|
235 |
Call cliBuilder.Append($"/ExeConfig:{ExeConfig}".CLIPath & " ")
|
236 |
End If
|
237 |
|
238 |
If AppBase Then
|
239 |
Call cliBuilder.Append("/AppBase ")
|
240 |
End If
|
241 |
|
242 |
If Not queue = PriorityLevels.null Then
|
243 |
Call cliBuilder.Append($"/queue:{CInt(queue)}")
|
244 |
End If
|
245 |
|
246 |
Dim NGen As New IORedirectFile(NgenInstaller.Ngen, cliBuilder.ToString & " /verbose")
|
247 |
Call NGen.Run()
|
248 |
Return NGen.StandardOutput
|
249 |
End Function
|
250 |
|
251 |
|
252 |
Delete the native images of an assembly and its dependencies from the native image cache.
|
253 |
To uninstall a single image And its dependencies, use the same command-line arguments that were used to install the image.
|
254 |
|
255 |
Note In the .NET Framework 4, the action uninstall * Is no longer supported.
|
256 |
</summary>
|
257 |
<param name="assemblyName">
|
258 |
The full display name of the assembly. For example, "myAssembly, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0038abc9deabfle5".
|
259 |
Only one assembly can be specified per Ngen.exe command line.
|
260 |
|
261 |
* Note You can supply a Partial assembly name, such As myAssembly, For the display And uninstall actions.
|
262 |
|
263 |
The explicit path of the assembly. You can specify a full or relative path.
|
264 |
If you specify a file name without a path, the assembly must be located In the current directory.
|
265 |
Only one assembly can be specified per Ngen.exe command line.
|
266 |
</param>
|
267 |
<param name="scenarios"></param>
|
268 |
<param name="ExeConfig">exePath, Use the configuration of the specified executable assembly.
|
269 |
Ngen.exe needs to make the same decisions as the loader when binding to dependencies. When a shared component Is loaded at run time,
|
270 |
using the Load method, the application
|
271 |
for example, the version of a dependency that is loaded. The /ExeConfig switch gives Ngen.exe guidance on which dependencies would be loaded at run time.</param>
|
272 |
<param name="AppBase">directoryPath, When locating dependencies, use the specified directory as the application base.</param>
|
273 |
Public Function Uninstall(assemblyName As String,
|
274 |
scenarios As NgenInstaller.Scenarios,
|
275 |
Optional ExeConfig As String = "",
|
276 |
Optional AppBase As Boolean = False) As String
|
277 |
|
278 |
Dim cliBuilder As StringBuilder = New StringBuilder("uninstall ", 1024)
|
279 |
Call cliBuilder.Append(assemblyName.CLIPath & " ")
|
280 |
Call cliBuilder.Append(scenarios.Description & " ")
|
281 |
|
282 |
If Not String.IsNullOrEmpty(ExeConfig) Then
|
283 |
Call cliBuilder.Append($"/ExeConfig:{ExeConfig}".CLIPath & " ")
|
284 |
End If
|
285 |
|
286 |
If AppBase Then
|
287 |
Call cliBuilder.Append("/AppBase")
|
288 |
End If
|
289 |
|
290 |
Dim NGen = New IORedirectFile(NgenInstaller.Ngen, cliBuilder.ToString & " /verbose")
|
291 |
Call NGen.Run()
|
292 |
Return NGen.StandardOutput
|
293 |
End Function
|
294 |
|
295 |
|
296 |
Update native images that have become invalid.
|
297 |
If /queue Is specified, the updates are queued For the native image service. Updates are always scheduled at priority 3, so they run When the computer Is idle.
|
298 |
</summary>
|
299 |
<param name="queue"></param>
|
300 |
Public Function Update(Optional queue As Boolean = False) As String
|
301 |
Dim cliBuilder As StringBuilder = New StringBuilder("update ")
|
302 |
If queue Then
|
303 |
Call cliBuilder.Append("/queue")
|
304 |
End If
|
305 |
|
306 |
Dim NGen = New CommandLine.IORedirectFile(NgenInstaller.Ngen, cliBuilder.ToString & " /verbose")
|
307 |
Call NGen.Run()
|
308 |
Return NGen.StandardOutput
|
309 |
End Function
|
310 |
|
311 |
|
312 |
Display the state of the native images for an assembly and its dependencies.
|
313 |
If no argument Is supplied, everything In the native image cache Is displayed.
|
314 |
</summary>
|
315 |
<param name="assemblyName"></param>
|
316 |
Public Function Display(assemblyName As String) As String
|
317 |
Dim NGen = New CommandLine.IORedirectFile(NgenInstaller.Ngen, "display " & assemblyName.CLIPath & " /verbose")
|
318 |
Call NGen.Run()
|
319 |
Return NGen.StandardOutput
|
320 |
End Function
|
321 |
|
322 |
|
323 |
Execute queued compilation jobs.
|
324 |
If a priority Is specified, compilation jobs With greater Or equal priority are executed.
|
325 |
If no priority Is specified, all queued compilation jobs are executed.
|
326 |
</summary>
|
327 |
<param name="queue"></param>
|
328 |
Public Function ExecuteQueuedItems(Optional queue As NgenInstaller.PriorityLevels = PriorityLevels.null) As String
|
329 |
Dim cli As String = "eqi "
|
330 |
|
331 |
If queue <> PriorityLevels.null Then
|
332 |
cli = cli & CStr(CInt(queue))
|
333 |
End If
|
334 |
|
335 |
Dim NGen = New CommandLine.IORedirectFile(NgenInstaller.Ngen, cli & " /verbose")
|
336 |
Call NGen.Run()
|
337 |
Return NGen.StandardOutput
|
338 |
End Function
|
339 |
|
340 |
|
341 |
Pause the native image service, allow the paused service to continue, or query the status of the service.
|
342 |
</summary>
|
343 |
Public Function Queue(action As QueueActions) As String
|
344 |
Dim cli As String = "queue " & action.Description
|
345 |
Dim NGen = New CommandLine.IORedirectFile(NgenInstaller.Ngen, cli & " /verbose")
|
346 |
Call NGen.Run()
|
347 |
Return NGen.StandardOutput
|
348 |
End Function
|
349 |
|
350 |
Public Enum QueueActions
|
351 |
|
352 |
Pause the native image service
|
353 |
</summary>
|
354 |
<Description("pause")> pause
|
355 |
|
356 |
allow the paused service to continue
|
357 |
</summary>
|
358 |
<Description("continue")> [Continue]
|
359 |
|
360 |
query the status of the service.
|
361 |
</summary>
|
362 |
<Description("status")> status
|
363 |
End Enum
|
364 |
#End Region
|
365 |
|
366 |
|
367 |
将当前目录下的所有的.NET程序都进行安装
|
368 |
</summary>
|
369 |
<ExportAPI("--install", Info:="Install all of the .NET program in the current directory.")>
|
370 |
Public Function Install(Optional PATH$ = "./", Optional installExe As Boolean = False) As String()
|
371 |
Dim files As IEnumerable(Of String)
|
372 |
|
373 |
If installExe Then
|
374 |
files = ls - l - r - {"*.exe", "*.dll"} <= PATH$
|
375 |
Else
|
376 |
files = ls - l - r - {"*.dll"} <= PATH$
|
377 |
End If
|
378 |
|
379 |
Dim runInstall = LinqAPI.Exec(Of String) _
|
380 |
_
|
381 |
() <= From assembly As String
|
382 |
In files
|
383 |
Let std_out = NgenInstaller.Install(assemblyName:=assembly, scenarios:=Scenarios.Profile)
|
384 |
Select std_out
|
385 |
|
386 |
Return runInstall
|
387 |
End Function
|
388 |
|
389 |
Public Sub Uninstall(savedState As IDictionary)
|
390 |
NgenFile(InstallTypes.Uninstall)
|
391 |
End Sub
|
392 |
|
393 |
Private Enum InstallTypes
|
394 |
Install
|
395 |
Uninstall
|
396 |
End Enum
|
397 |
|
398 |
Public ReadOnly Property Ngen As String
|
399 |
Get
|
400 |
Dim envDir As String = RuntimeEnvironment.GetRuntimeDirectory()
|
401 |
Dim ngenPath As String = IO.Path.Combine(envDir, "ngen.exe")
|
402 |
Return ngenPath
|
403 |
End Get
|
404 |
End Property
|
405 |
|
406 |
Private Sub NgenFile(options As InstallTypes)
|
407 |
|
408 |
'Dim exePath As String = Context.Parameters("assemblypath")
|
409 |
|
410 |
|
411 |
|
412 |
|
413 |
|
414 |
' Dim fileKey As String = "ngen" & i
|
415 |
|
416 |
|
417 |
' Dim ngenFileName As String = Context.Parameters("ngen" & i)
|
418 |
|
419 |
' Dim argument As String = (If(options = InstallTypes.Install, "install", "uninstall")) & " """ & fileFullName & """"
|
420 |
|
421 |
|
422 |
|
423 |
|
424 |
|
425 |
|
426 |
|
427 |
|
428 |
|
429 |
|
430 |
|
431 |
|
432 |
|
433 |
|
434 |
End Sub
|
435 |
End Module
|
436 |
End Namespace
|