[AX]AX2012 X++编译成CIL

AX2012 X++编写的batch job必须首先编译成.net的CIL语言才能运行,预先编译的CIL比X++的解释型p-code速度要快。X++的代码在保存到AOT的时候自动编译成p-code,要把p-code编译成CIL需要执行AOT > Add-ins > Incremental CIL generation from X++,还有一个full CIL generation from X++,这个动作在安装系统时进行一次,编译生成的CIL以.netmodule形式的文件保存在类似目录C:\Program Files\Microsoft Dynamics AX\60\Server\MicrosoftDynamicsAX\bin\XppIL\下。

可以使用Global ::runClassMethodIL()来以CIL方式运行X++代码,具体看下例:

class DemoClassCIL
{
}

// Called by:  main, countNestedLoopsContainer.
public server static str countNestedLoops(int _numOfLoops)
{
    int runningSum = 0, ii, kk;

    for (ii = 0; ii < _numOfLoops; ii++)
    {
        for (kk = 0; kk < _numOfLoops; kk++)
        {
            runningSum++;
        }
    }
    return "Final sum is: " + int2str(runningSum);
}

// Called by:  countNestedLoopsWrapper.
private server static container countNestedLoopsContainer(container _cNumOfLoops)
{
    int runningSum = 0, ii, kk;
    int numOfLoops;
    str sSumInString;
    container cReturn;

    numOfLoops = conPeek(_cNumOfLoops, 1);

    sSumInString = DemoClassCIL::countNestedLoops(numOfLoops);

    return conPoke(cReturn, 1, sSumInString);
}

// Called by:  main.
public server static str countNestedLoopsWrapper(int _numOfLoops)
{
    container cFromCIL;

    new XppILExecutePermission().assert();

    cFromCIL = Global::runClassMethodIL
        ("DemoClassCIL",             // Or use classStr function.
        "countNestedLoopsContainer", // Or use staticMethodStr function.
        [_numOfLoops]
        );

    return conPeek(cFromCIL,1);
}

// Run this method, from the MorphX code editor,
// or from a job under AOT > Jobs.
public server static void main(Args _args)
{
    int startTicksInterp, endTicksInterp;
    int startTicksCIL, endTicksCIL;
    str resultStrInterpreted, resultStrCIL;
    int numLoopsWanted = 987;

    // These first two calls ensure DLL files are loaded,
    // before we can do a fair comparison.
    DemoClassCIL::countNestedLoops(numLoopsWanted);
    DemoClassCIL::countNestedLoopsWrapper(numLoopsWanted);

    startTicksInterp = WinAPIServer::getTickCount();
    resultStrInterpreted = DemoClassCIL::countNestedLoops(numLoopsWanted);
    endTicksInterp = WinAPIServer::getTickCount();

    startTicksCIL = WinAPIServer::getTickCount();
    resultStrCIL = DemoClassCIL::countNestedLoopsWrapper(numLoopsWanted);
    endTicksCIL = WinAPIServer::getTickCount();

    Global::info(strFmt
        ("%1 (Interpreted: %2), (CIL: %3).",
        resultStrCIL,
        endTicksInterp - startTicksInterp,
        endTicksCIL - startTicksCIL
        ));

}

Global::runClassMethodIL()函数返回container,所以countNestedLoopsContainer()使用container对真正的计算过程countNestedLoops()做了封装,main()方法中比较了直接运行X++和CIL的速度,记得运行前执行下AOT > Add-ins > Incremental CIL generation from X++,在我的环境中得到的结果是:

Final sum is: 974169 (Interpreted: 984), (CIL: 16).

可以看到CIL比解释型p-code要快很多。

需要注意的是动态运行X++的函数evalbuf和runbuf是不能编译成CIL的。从AOT中移除一些X++的方法后,要从CIL中移除相应的CIL代码需要执行full CIL generation,增量CIL generation不会从CIL中移除这些代码。系统必须成功执行一次full CIL编译才能运行服务、SSRS报表及批处理任务。在目前版本的AX中任何一个类的任何一个方法有错误就会导致整个CIL编译失败, Cumulative Update 2 for Microsoft Dynamics AX 2012 对此做了些修正,无效的P-CODE编译时会抛出异常,不会影响到余下代码的编译。

更多内容参见http://msdn.microsoft.com/EN-US/library/gg839855

 

posted @ 2012-08-27 13:02  断水流  阅读(1589)  评论(0编辑  收藏  举报