In this post we describe the new AXBuild.exe utility that you can use to increase the speed of a compilation of all X++ source code and metadata validation. AXBuild became available in November 2013 as part of cumulative update 7 (cu7) for Microsoft Dynamics AX 2012 R2.
There are initial clarifications to understand about AXBuild:
- The legacy compilation options in the MorphX client remain available.
- AXBuild involves the compilation of X++ source code into AX p-code and metadata validation, but it does not involve the subsequent generation from p-code into .NET Framework CIL.
- AXBuild can compile all the elements in the system, but its scope cannot be narrowed to compiling just a subset of classes and other elements.
Sometimes a compilation of all the AOT elements is needed. Such occasions include:
- Setup of AX 2012 R2.
- Installation of upgrades and hotfixes.
- Migration from development to test, staging, and production environments.
1 Phases of any X++ Compile Process
In the earlier blog post, How the X++ Compiler works for AX2012 we gave a high level explanation of the processes that compile X++. Three major phases were described:
- Phase 1: Declarations and method signatures.
- Phase 2: Metadata validation and method bodies.
- Phase 3: Recompilation of elements that had preliminary errors.
These phases apply to the compile process under AXBuild just as they apply to the compile process you initiate by clicking in the MorphX client menus.
2 Legacy Client Tier Compile of Full X++
Until today the X++ compilation and metadata validation processes were always executed on the client tier using one single thread. Figure 1 represents the X++ compilation process that runs on the client. The client requests metadata from the Application Object Server (AOS) tier. Metadata is needed for every element that must be compiled or validated. The metadata stored in SQL Server is de-serialized by the AOS into the internal representation of a TreeNode. Then the metadata is transferred over the network to the client. If the client and AOS are installed on the same computer (the “one box” configuration), a process-to-process communication over RPCs is used in place of a two tier network communication.
After the client received the metadata, the client compiles the X++ source code. The X++ source code is translated in AX p-code. The AX runtime understands the p-code and can execute it. The compile process also validates any references to other elements that are specified through properties. Information about any errors is written to the compilation log. After each element is compiled, the client enriches its representation of the element with updated metadata and p-code. Next the client sends the enriched representation to the AOS. The AOS saves the updated element in the model store database.
Figure 1. Metadata transfer during compilation and validation process.
Agile development benefits from the client tier compile of X++, because the development cycles often require compilation of a narrow subset of all classes and forms etc. In the MorphX client the developer can compile individual elements such as one class. The developer can test the change, fix the code, recompile the one class, and retest. The compilations of individual classes complete in a second or two, so these agile development cycles are kept efficient.
Also, the compiler on the client tier is fully leveraged and integrated with productivity tools like Cross Reference, IntelliSense, and Visual Studio.
3 AOS Tier Compile of Full X++ (only in cu7)
For a full X++ compile, the legacy client tier scenario is slow. Having the compilation run on the client is ironic for the following reasons:
- One irony is that the source code and the metadata are on the server computer, yet the compilation that needs the source and metadata is run on the client computer.
- The server computer is typically more powerful in terms of hardware.
In cu7 we are introducing AXBuild, an X++ compilation management utility that you run on the same server computer that hosts the AOS. AXBuild achieves its speed gains for the following major reasons:
- The client is excluded from the scenario. This eliminates the network communication from the AOS to the client and back. See Figure 2.
- AXBuild runs on a server computer that typically has more powerful hardware than the client computer has.
- AXBuild runs the compilation as a 64 bit process, instead of a 32 bit process as with MorphX. This allows more active memory to be addressed.
- AXBuild compiles subsets of AOT elements in parallel, whereas the client compilations process uses just a single thread.
Figure 2. Parallel compilation on the server tier.
Exclusion of the Client Tier: In the legacy full X++ compilation that runs on the MorphX client, the network transmission of information from the AOS to the client and back adds 28% to the wall clock duration of the compilation process. Even if the client is installed on the same computer with the AOS, transmissions through RPCs are needed.
Parallel Compilation: AXBuild starts multiple temporary AOS processes. These AOS worker processes run in parallel. AXBuild coordinates their compilation acitivities. AXBuild does the following:
- Assigns a subset of AOT elements for compilation to each temporary AOS.
- Collects the results from each temporary AOS, and writes the results to a single combined compilation log file.
AXBuild calculates the optimal number of temporary AOS workers as best it can, and it reports its calculation to its console. The calculation is based on the number of CPUs that the server computer has. However, you can fine tune and control the number of AOS workers by using the /workers= parameter. Factors you might consider include:
- Amount of active memory that the server computer has.
- CPU demands that other processes might make while the compilation runs.
4 New compiler constraints
Calls to COM Objects Cannot be Chained Together
When your X++ method contains calls to COM objects, the syntax shortcut of chaining methods calls together can cause the compiler to report an error. The simple solution is to rewrite a couple lines of code make the variable types more explicit and discoverable by the compiler.
A. Example that Fails: The following X++ code example chains the method2 call to the end of the method1 call. The server compiler reports an error for the method2 call:
COM comInstanceA = new COM("My_COM_Type_A");
comInstanceA.method1().method2(); // methods call chained together
Underlying Details: Often COM objects that are called by X++ code are installed only on the client tier, and are not installed on the server tier. In the preceding code example, the underlying problem is that the server compiler cannot know whether method1 returns another COM object or just an integer. A plain integer would not have a method named method2, so the compile cannot validate the call to method2. For the call to method1, the compiler accepts the late-binding approach by inserting into the p-code a call to the COM method named dispatch.
B. Example that Succeeds: The following rewrite of the preceding X++ code example eliminates the chain, and the server compile passes without error:
COM comInstanceA = new COM("My_COM_Type_A");
comInstanceB = comInstanceA.method1();
Underlying Details: In the preceding code example, the X++ compiler is told by an explicit type declaration that variable comInstanceB is a COM object. This gives the compiler justification to insert a call to the dispatch method for method2.
If you install cu7 all the application code exposing this pattern has been addressed and fixed, so no compilation errors should be reported. However if you choose not to install the application code portion of the cumulative update, you are going to get some compilation errors due to this pattern (Figure 3).
Figure 3. Compilation errors generated if application code is not installed as part of cu7 setup.
5 Performance Gain
The performance gain depends on the available resources in the computer where the parallel compilation process is being executed, including number of CPU’s and memory available. However to put some numbers in perspective, we have taken some careful measurements.
- MorphX client, AOS and SQL Server installed on the same computer.
- 4 Cores 3.7 GHertz.
- Hyper-Threading enabled, which logically doubles the CPU count.
- 32 GBytes of physical active memory.
- 6.0 Gigabits/s SATA Controller
- Windows Server 2012
- SQL Server 2012 Enterprise with SP1 (no memory constraint)
- Windows virtual page caching disabled.
- Fresh AX 2012 R2, with cu7 installed.
5.2 Results of Performance Test
- Compilation using AXBuild.exe running 9 AOS workers: 10 minutes and 40 seconds.
- Compilation using MorphX client (for comparison): 2 hours and 26 minutes.
Both measurements were done using the same hardware and software setup.
6 Miscellaneous Details
- When you use the AOT of the MorphX client to import a .XPO file, the resulting X++ compile occurs only on the client tier (.XPO files import operation remains unchanged in cu7).
- All generation of .NET Framework CIL remains unchanged in cu7.
- The MorphX client is the Development Workspace window in ax32.exe.
- Even though the name of the AOS program ax32serv.exe contains ‘32’, it is a 64 bit program.
- Hotfix KB2844240 is still relevant, getting better performance during compilation on top of AXBuild and legacy compilation from the client. This hotfix does not have to be installed independently from cu7, it is already included as part of the cumulative update, however you have to make sure it is executed against your model store using "AxUtil.exe schema".
- AXBuild.exe needs to be executed with hot-swap disabled. For more information about hot-swap mode refer to Hot-swapping of .NET Assemblies in the AOS [AX 2012].
- AXBuild.exe is not a tool that can be ported independently from cu7 (copying it to a computer with a previous Dynamics AX2012 R2 version), since it needs additional support introduced into the Ax32Serv.exe (AOS) and other binaries only available starting in cu7 version.
- For additional important information about AXBuild, see our formal Help topic on MSDN titled AxBuild.exe for Parallel Compile on AOS of X++ to p-code.