FileLoadException
,常见错误是其中某些依赖没有找到,这个时候异常信息应该是类似:一个xxx的依赖没有找到;这个问题很好解决,确定缺少的依赖补充上就可以了,可以使用 dumpbin
工具查看相关的依赖:1 | dumpbin /dependents target.dll |
未能加载由xxx.dll导入的过程
,除了这些,几乎没有什么有用的错误信息让我们来确定到底出现了什么问题。一般来说,按照目前我遇到的问题,这个一般都是对应的库文件调用了当前平台不支持的api导致的。当然,这个问题不易在开发的机器上发现,因为能调用到这个api就代表调试机器上有对应平台版本的SDK,一般如果前期没有发现到这个问题,那么问题被发现时肯定是在生成环境,所以需要开发人员注意调用接口的支持平台。 要定位是什么接口导致的问题,需要借助其他的调试工具来排查。微软的 Windows SDK 提供了对应的工具 gflags.exe
,借助这个工具,我们可以在调试的过程中看到详细的动态库加载信息,在这些信息中可以定位到底是什么接口导致库文件加载失败。当然,你需要在出现问题的机器上使用这个工具进行操作,并通过 Visual Studio 进行远程调试。
如上图显示,通过输入你程序的名字和开启 Show loader snaps
开关,应用后使用 Visual Studio 进行调试,可以在输出窗口看到详细的加载信息:
在上一篇文章中,我们已经对 Loop Invariant
概念有一个简单的了解,在文章的最后提到的 Loop Invariant
将在这篇文章做一个简单的介绍。
如果你了解 C#
程序的运行,应该知道 C#
代码先被编译器编译为 MSIL
中间代码,在实际运行的时候才通过 JIT
编译器将 MSIL
代码编译成机器代码并运行。因此,编译器有两个时段可以对代码进行优化:
JIT
来完成的。而这篇文章也是围绕微软最新的 RyuJIT
编译器来展开,其可能与旧的 JIT
有所区别,但是应该差异不大。首先看一下微软对 Loop Invariant Code Hoisting
的说明:
This phase traverses all the loop nests, in outer-to-inner order (thus hoisting expressions outside the largest loop in which they are invariant). It traverses all of the statements in the blocks in the loop that are always executed. If the statement is:
- A valid CSE candidate
- Has no side-effects
- Does not raise an exception OR occurs in the loop prior to any side-effects
- Has a valid value number, and it is a lclVar defined outside the loop, or its children (the value numbers from which it was computed) are invariant.
JIT
从外到内遍历所有的循环嵌套。它遍历循环嵌套结构中始终会被运行的BasicBlock
(这是JIT
里的类型,这里暂不展开,你可以暂时将其理解为编译器的基本类型)里的语句,并且这些语句符合以下条件:
CSE
上面提到的始终会被运行的循环嵌套(loop that are always executed), 如何理解? 嗯…,简单来讲,我们知道的循环结构,例如大部分编程语言都会有的 for loop 和 do while loop,这两种循环嵌套中,do while loop 就符合一定会被执行的循环嵌套,因为循环判断在一次循环后才会执行,而有些for loop 也可以被转换为 do while loop, JIT
会判断这个loop能否转换为do while loop后才进行后续的 loop hoisting 操作。
Utilizes value numbers to identify redundant computations, which are then evaluated to a new temp lvlVar, and then reused.
利用数字来识别(替代?)多余的计算,然后将它们计算为新的临时值,并重复利用。就如上篇文章中for循环中的 x+y
。
观察RyuJIT
中用于判定CSE
的函数片段:
1 | /***************************************************************************** |
Loop-Hoisting
还有颇多细节这里并没有覆盖,有兴趣可以去看源码:https://github.com/dotnet/coreclr/blob/master/src/jit/optimizer.cpp