TechnoFunctional Approach to Dynamics AX Advanced Warehousing Performance Problems Part 2 — Waves

TechnoFunctional Approach to Dynamics AX Advanced Warehousing Performance Problems Part 2 — Waves

So often I go on sites and find repeatedly that the most complicated technical solutions can often be resolved by just talking to people. Point demonstrated here where we will use less than 5 lines of code to fix a problem that has been bothering quite a few implementations because somebody took the time to talk to me and explain the business requirements while I listened. From there, a seemingly complicated problem resolved itself quite nicely.


One thing that hasn’t changed whenever you have dynamic data retrieval, you fix it by simply making it less dynamic. In this case, you need to have some agreed upon filter. For example, does a particular wave only apply for a certain Item group or at a certain time? Essentially, you finish the requirements by changing the focus from being able to do everything dynamically to being able to do what we need to do at the time of running the application. Let’s fix this with less than 5 lines of code:

1st: Create a Parameter that will help select the correct wave template rather than iterating through all of them. In other words, agree upon a restrictive condition with the users.

In this example, I’m using ItemId, but note that I used another condition in the real example which I can’t talk about because it is client code. Note the method WHSWaveTable::assignOrCreateWave is where the problem starts.

Notice how I also make it a default parameter which is key so that in the event of failure to match an ItemId, the default logic executes.

2nd: Alter the WHSPoolProdBOM::createWave method to pass in the parameter that you will use for a filter. All you are really doing here is following a call stack. You are logically telling AX that you are going to restrict the templates that it uses to instantiate and run a query so as to not iterate through all possible combinations of templates.

3rd: Restrict the list from going over all wave templates for a given type by restricting the WHSWaveTemplateTable::waveTemplateCachedQuery method.

This was the money shot towards solving the issue. AX retrieves the list of Wave templates in the waveTemplateCachedQuery method. Microsoft must have known about the performance problems with this and made an attempt to speed up the mechanism of data retrieval through caching which was helpful, but it’s not the same as you having the critical advantage of being able to get an agreed upon filter condition. If a client has 100 wave templates, all the caching in the world won’t stop the slowness. Plus, instantiating and running a brand new query for each wave template is expensive. You need to limit the wave templates that are iterated over by altering this method.

4th, Just add a simple “where” clause condition and watch things really speed up on Production Orders with lots of BOM components and implementations with lots of wave templates. Also add that where condition column value to the WaveTemplateTable so you can query it.

I added a column to the Wavetemplate table which stored the filter value for the value and then went into the Wave setting form and made it copy the value to that table. That made it so that I could easily go into the code and provide a simple “if” to tell it to only run the special performance optimized code if a condition has been provided. Otherwise, go with the default.

And there you have it. 5 Lines of code (more like 8 words of code) to solve a complicated problem. All of this was made possible because the business analysts told me that the wave template could be matched by a certain filter condition – a key advantage that the original developers did not have at the time of development. That’s why I have a hard time calling things bugs in performance. No matter who you are, you can’t code for every possible situation at the time of conception. Big high-volume or complicated supply chain setup performance problems tend to not be detected during initial ERP vendor development – always been that way. But you can see where the solution became pretty easy to fix with some user feedback.

Compare this to the previous post and notice how the assign or create wave method has completely disappeared as well as the expensive instantiating a query and queryrun events – down to just 2 seconds where I’m actually executing the waves also (which is still faster than just creating the waves originally).

Note: you can almost equivocate this functionally by simply restricting the number of wave templates available for each site and location out of the box. We are done with Waves for now but not done with our adventures of advanced warehousing. Until the next time..