mfp's two cents

...on Dynamics AX Development!
  • mfp's two cents

    Pre-order Inside Microsoft Dynamics AX 2012

    • 2 Comments

    We are heading for a true power demonstration from Microsoft in the fall of 2012. A long line of exciting products will be released, including Windows 8, Windows Server 2012 and Microsoft Surface

    …and the probably most anticipated of them all:
    Inside Dynamics AX 2012.

    Pre-order your copy today.

    Abstract:

    Dig into the architecture and internals of Microsoft Dynamics AX 2012 - with firsthand insights from the team that designed and developed it. Targeted for solution developers and system implementers, this guide focuses on programming and customization capabilities - including key architectural principles, the application model, framework, and tools. Topics include: Architecture and development environment, including MorphX Microsoft Visual Studio tools for Microsoft Dynamics AX X++ programming language Microsoft SQL Server reporting and analytics Models Core development concepts Extending and customizing Microsoft Dynamics AX Performance and security considerations Workflow Best practices Note: Readers should have working knowledge of SQL and OOP concepts to gain max benefit from this book.

  • mfp's two cents

    Memory consumption of tables variables

    • 3 Comments

    I recently made an interesting discovery, that I want to share with you. I was investigating an recursive algorithm that scaled nicely; until it ran out of memory. For each level of the recursion a new class instance was created – this class contained multiple member variables of type Table (as in CustTable). I decided to measure the memory footprint of this construct, and I was much surprised by my findings.

    Consider these 3 classes – that each stores the same amount of data, but in different ways:

    /// <summary> 
    
    /// Test class containing a table buffer and setting 20 fields 
    
    /// </summary> 
    
    class Class1 
    
    { 
    
        BOMCalcTrans bomCalcTrans; 
    
        public void new() 
    
        { 
    
            bomCalcTrans.ConsumptionVariable = 50; 
    
            bomCalcTrans.ConsumptionConstant = 50; 
    
            bomCalcTrans.CostPriceQty = 50; 
    
            bomCalcTrans.CostPrice = 50; 
    
            bomCalcTrans.CostPriceQtySecCur_RU = 50; 
    
            bomCalcTrans.CostMarkup = 50; 
    
            bomCalcTrans.NumOfSeries = 50; 
    
            bomCalcTrans.SalesPriceQty = 50; 
    
            bomCalcTrans.SalesMarkupQty = 50; 
    
            bomCalcTrans.CostMarkupQty = 50; 
    
            bomCalcTrans.CostMarkupQtySecCur_RU = 50; 
    
            bomCalcTrans.CostPriceSecCur_RU = 50; 
    
            bomCalcTrans.CostMarkupSecCur_RU = 50; 
    
            bomCalcTrans.NetWeightQty = 50; 
    
            bomCalcTrans.CostPriceUnit = 50; 
    
            bomCalcTrans.SalesPrice = 50; 
    
            bomCalcTrans.SalesMarkup = 50; 
    
            bomCalcTrans.SalesPriceUnit = 50; 
    
            bomCalcTrans.SalesPriceFallBackVersion = 'abc'; 
    
            bomCalcTrans.CostPriceFallBackVersion = 'def'; 
    
        } 
    
    } 
    
    /// <summary> 
    
    /// Test class containing a hashTable with 20 key/value pairs 
    
    /// </summary> 
    
    class Class2 
    
    { 
    
        System.Collections.Hashtable hashTable; 
    
        public void new() 
    
        { 
    
            hashTable = new System.Collections.Hashtable(); 
    
            hashTable.Add(fieldNum(bomCalcTrans,ConsumptionVariable), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,ConsumptionConstant), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPriceQty), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPrice), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPriceQtySecCur_RU), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostMarkup), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,NumOfSeries), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesPriceQty), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesMarkupQty), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostMarkupQty), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostMarkupQtySecCur_RU), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPriceSecCur_RU), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostMarkupSecCur_RU), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,NetWeightQty), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPriceUnit), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesPrice), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesMarkup), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesPriceUnit), 50); 
    
            hashTable.Add(fieldNum(bomCalcTrans,SalesPriceFallBackVersion), 'abc'); 
    
            hashTable.Add(fieldNum(bomCalcTrans,CostPriceFallBackVersion), 'def'); 
    
        } 
    
    } 
    
    /// <summary> 
    
    /// Test class containing 20 member variables with values 
    
    /// </summary> 
    
    class Class3 
    
    { 
    
        InventQty bomCalcTransConsumptionVariable; 
    
        InventQty bomCalcTransConsumptionConstant; 
    
        CostPrice bomCalcTransCostPriceQty; 
    
        CostPrice bomCalcTransCostPrice; 
    
        CostPriceSecCur_RU bomCalcTransCostPriceQtySecCur_RU; 
    
        CostPrice bomCalcTransCostMarkup; 
    
        InventQty bomCalcTransNumOfSeries; 
    
        InventSalesPrice bomCalcTransSalesPriceQty; 
    
        InventSalesMarkup bomCalcTransSalesMarkupQty; 
    
        CostMarkup bomCalcTransCostMarkupQty; 
    
        InventPriceMarkupSecCur_RU bomCalcTransCostMarkupQtySecCur_RU; 
    
        CostPriceSecCur_RU bomCalcTransCostPriceSecCur_RU; 
    
        CostPriceSecCur_RU bomCalcTransCostMarkupSecCur_RU; 
    
        ItemNetWeight bomCalcTransNetWeightQty; 
    
        PriceUnit bomCalcTransCostPriceUnit; 
    
        CostingVersionId bomCalcTransCostPriceFallBackVersion; 
    
        InventSalesPrice bomCalcTransSalesPrice; 
    
        InventSalesMarkup bomCalcTransSalesMarkup; 
    
        PriceUnit bomCalcTransSalesPriceUnit; 
    
        CostingVersionId bomCalcTransSalesPriceFallBackVersion; 
    
        public void new() 
    
        { 
    
            bomCalcTransConsumptionVariable = 50; 
    
            bomCalcTransConsumptionConstant = 50; 
    
            bomCalcTransCostPriceQty = 50; 
    
            bomCalcTransCostPrice = 50; 
    
            bomCalcTransCostPriceQtySecCur_RU = 50; 
    
            bomCalcTransCostMarkup = 50; 
    
            bomCalcTransNumOfSeries = 50; 
    
            bomCalcTransSalesPriceQty = 50; 
    
            bomCalcTransSalesMarkupQty = 50; 
    
            bomCalcTransCostMarkupQty = 50; 
    
            bomCalcTransCostMarkupQtySecCur_RU = 50; 
    
            bomCalcTransCostPriceSecCur_RU = 50; 
    
            bomCalcTransCostMarkupSecCur_RU = 50; 
    
            bomCalcTransNetWeightQty = 50; 
    
            bomCalcTransCostPriceUnit = 50; 
    
            bomCalcTransSalesPrice = 50; 
    
            bomCalcTransSalesMarkup = 50; 
    
            bomCalcTransSalesPriceUnit = 50; 
    
            bomCalcTransSalesPriceFallBackVersion = 'abc';  
    
            bomCalcTransCostPriceFallBackVersion = 'def'; 
    
        } 
    
    }

    Now; let us create 1,000,000 instances of each and store them all in a List(Types::Class), and measure the memory footprint of each type of the 3 classes – running as IL and running as pcode.

    mem

    Notice that using a table as a member variable consumes 6x as much memory as having each field as a member – apparently there is a huge overhead associated with the xRecord+Common functionality.

    My conclusion – apparently you cannot have nice code and low memory consumption at the same time. My advice – be careful when using tables as member variables, especially in batch scenarios, i.e. classes derived from RunBaseBatch or used by same.

Page 1 of 1 (2 items)

August, 2012

mfp's two cents

...on Dynamics AX Development!