Header Image

Translate

woensdag 27 juli 2016

Ax 2009 performance bij opbouwen formulier met grid

Performance is nooit te goed en als je iets snel moet doen is het systeem altijd wel te traag. Maar soms is het ook raar. Normaal kan je performance terug leiden tot een index, tot een display/edit methode of veel client/server communicatie. Maar soms ook niet.

Bij een Ax 2009 gebruiker waren al diverse reputabele partijen geweest vanwege performance problemen die al diverse punten hebben aangehaald. Voornamelijk netwerk topologie punten. Maar alsnog geen soelaas.

Situatie schets; de servers worden gehost in een datacenter. Gebruikers hebben een thin client die een remote desktop verbinding maken met een terminal server (TS) in dit datacenter. In dit datacenter staat de Ax AOS met op diezelfde server de database. Zelf als externe Ax consultant had ik via RDP toegang tot de servers. Aangezien de TS nog wat extra software had voor de eindgebruikers het melden even waard. De TS zelf is Windows 2012 R2, de server zelf is Windows 2008. 

Eigenlijk kwam het terug tot dit; een standaard tabel, de InventJournalTrans op een schoon formulier met enkel een tab en een grid als admin ging de performance dramatisch onderuit als alle velden op de grid werden opgenomen. Als je het opende:

Her duurde tot wel 30 seconden voordat het scherm verder werd opgebouwd. En dan nog; het scherm werd zichtbaar opgebouwd:


Het klikken tussen de records zat merkbaar een vertraging in: duurde soms enkele seconden voordat een regel gearceerd werd. Eigenschappen van het form:
 - Kaal formulier met één tab, één grid, > 40 velden
 - Geen edit/display methoden enkel velden dit in de tabel zitten. 
 - Openen vanuit AOT, geen rechten, geen methoden geïmplementeerd(init, run, active, executeQuery, linkactive), eigen queries, sortering or andere properies van de componenten.Zelfs niet eens de moeite genomen de tab een label te geven.
Via de tabel-browser van Ax was de tabel met al zijn velden wel snel benaderbaar.

Bij minder velden (< 20) ging het goed en snel. De situatie is echter, dat na minimaliseren en restoren van het form de performance ineens goed was bij meer dan 20 velden. Deze code opgenomen onder een knop:
    WinAPI::showWindow(element.hWnd(), 6); // 6 = minimize
    WinAPI::showWindow(element.hWnd(), 9); // 9 = restore
Het scherm knippert even, maar de performance is uitstekend. Het opstarten van het formulier is echter nog steeds traag.

Het feit dat de schermen snel zijn na een minimize/restore  geeft mij aan dat het probleem niet in Ax of in de netwerk verbinding zit. Maar waarom is de tabel-browser dan wel snel? Deze velden worden dynamics toegevoegd...Uiteindelijk kwam ik er achter dat verborgen velden hetzelfde effect had:


In de run:


De refreshForm:


Het direct zichtbaar maken in de run (de na de super in de run meteen refreshForm aanroepen) maakte het systeem al wel wat sneller, maar het selecteren van andere records bleef traag.

Een aantal dingen die ik geprobeerd heb:
- Kernel AOS/client bijwerken (laatste versie op dit moment: 5.0.1600.3696)
- Al het maatwerk in de basis zoals SysSetupFormRun, Info, Application etc. die eventueel problemen zou kunnen veroorzaken verwijderen (echt de laag zelf verwijderen).
- Diverse calls zoals yield(), winapi calls die ik kon vinden die mogelijk messages voor een form afhandelde / opschoonde. 
- Applicatie zaken (verwijderen UAC, verwijderen *.I, met herstart AOS uiteraard)

Andere bevindingen;
- Vanaf de TS was het sneller dan rechtstreeks op de server. Dit kan verklaard worden doordat resources op de server beperkter zijn (SQL server wil nogal geheugen claimen). Het scherm opende wel sneller, maar het selecteren van andere records bleef traag tot het scherm geminimaliseerd / gerestored is.
-  Het maakt niet uit voor de server: Windows 2012 R2 met client applicaties en de Ax client die verbinding maakt met een Windows 2008 AOS+DB heeft dezelfde eigenschap als alles op één Windows 2008 machine (client en AOS en DB)
- Aangezien het minimaliseren / restoren van het Form al het euvel verhelpt en de kaalheid van het form, is het mijn insteek dat het niet in de applicatie van Ax zit maar mogelijk in de Ax client zelf icm windows al-dan-niet icm een derde applicatie.

Uiteindelijk heb ik deze functionaliteit meegenomen in de applicatie;





Dus alleen velden dit zicthbaar zijn aan het eind van de init -> verbergen


Dus alles dat inzichtbaar is gemaakt, weer zichtbaar maken. Een minimize/restore kan ook, zie uitgecommentarieerde code. Maar dat flikkert wel het scherm dus.

De timeout in de run:


Dit is geen oplossing voor het probleem, maar meer een workaround voor de symptomen. Tot zover... mocht iemand zoeken naar performance problemen, kan je hier misschien wat mee. Als iemand anders nog ideeën of tips heeft,  dan hoor ik dat ook graag.

maandag 2 mei 2016

Verkeerde BIN directory

Bij het gebruik van externe DLL bestanden maak ik gebruik van Reflection. Deze laad ik daarmee dynamics vanuit de client BIN directory. Dit omdat .NET assemblies die je toevoegt als Reference fouten geeft bij ontwikkelaars die de DLL niet hebben.

Om de DLL te laden, gebruik ik mede de code : xinfo::directory(DirectoryType::Bin)

Echter was na een server upgrade een batchproces ontregeld. Reden was dat een DLL niet gevonden kon worden. Het bleek dat deze code een oude, 32-bit Bin directory terug gaf. Vanaf dezelfde machine, zelfde account vanaf mijn machine RDP:

 Op dezelfde server, door een gebruiker RDP: 
Oorzaak was een fout in het configuratie bestand. De klant gebruikte een configuratie bestand welke een fout had: 
Hier ontbrak de (x86) markering die de juiste locatie bevat. 


vrijdag 22 januari 2016

Lege label waarde

Soms wil je een label maken wat alleen een waarde in een bepaalde taal heeft. Als je dan een andere taal niet opgeeft, krijg je de leuke '@xxx15' melding dat je erop attendeert dat een bepaalde label geen vertaling heeft. Maar soms op rapportages wil je nou juist dat bepaalde talen geen label hebben.

Als je probeert een spatie op te voeren bij een label, trimt Ax standaard de invoer. Dus je kan niet even een spatie erin zetten.

Simpele oplossing: bij een lege label waarde, gebruik dan een NBSP (non-breaking space). Houd de linker ALT ingedrukt, voer 255 in op je numpad en voila: een spatie welke Ax niet trimt.













Simpel maar effectief:

dinsdag 8 december 2015

Kopieer een groot binair bestand naar de server

De meest makkelijke manier om een binair bestand naar de server te communiceren is met behulp van de bindata componenten:
Effectie wordt deze wijze ook gebruikt om documenten in de database op te slaan in document-verwerking functionaliteit. Hier gebruik ik even de 'appendToFile'. Vreemd genoeg is in Ax 2009 (SP1) geen FileIOPermission nodig, maar dat is even niet het punt. Het punt is als het bestand te groot wordt (12MB):


"The Dynamics Ax session is no longer valid" op het moment dat de setData wordt aangeroepen. Dit gebeurd ook als je documentverwerking opslaat in de database en even het limiet hoog genoeg zet.

Je kan proberen de getData eerst toe te wijzen aan een container, maar wederom gaat bij setData dit fout.

Het bindata object heeft een methode: copyData. Leuke functie met een offset en grootte. Zou je de buffer in delen naar de server kunnen sturen, maar helaas:

Dit is zelfs erger. Deze actie zorgt ervoor dat de AOS gewoon crashed.


De enige oplossing die ik zover heb gevonden is het eerst kopieren naar een kleine buffer en die dan serverside toe te voegen:


Code:

static void Example_File2_C(Args _args)
{
    BinData clientBin    = ClassFactory::makeObjectOnClient(classnum(BinData));
    BinData clientBinTmp = ClassFactory::makeObjectOnClient(classnum(BinData));
    BinData serverBin    = ClassFactory::makeObjectOnServer(classnum(BinData));
    str fileName = @"C:\Ax\Client\file2.bin";
    str fileNameServer = @"C:\Ax\Server\file2.bin";
    int fileSize;
    int offset;
    int bufferSize = 1024*1024; // 1MB;
    ;
    #file

    clientBin.loadFile(fileName);
    fileSize = clientBin.size();
    offset = 0;
    while (offset < fileSize)
    {
        clientBinTmp.copyData(clientBin, offset, bufferSize);

        serverBin.setData(clientBinTmp.getData());
        serverBin.appendToFile(fileNameServer);

        offset += bufferSize;
    }

    info('Done!');
}

Dit behoud niet de bestandsinformatie (gemaakt op datum, NTFS beveiliging etc.) maar de data is serverside. Nog een leuke progress-bar om de gebruiker tevreden te houden en je hebt een manier. 

maandag 7 december 2015

Unable to load page–Ax portal via business connector

Een nieuwe installatie van een Ax 4.0 sharepoint omgeving op een windows 2008 machine gaf een fout bij het maken van de PDF: ‘Unable to load page.’ in de eventlog. De PDF zelf is intern zo goed als leeg::

Er zijn veel artikelen te vinden over dit onderwerp, en de fout leek veroorzaakt te worden door de Ax client, of in dit geval de business connector gezien dat het een portal is. Maar SP2 met de hotfix is geïnstalleerd en bij het starten van de setup zegt de setup-util dat de versie al geïnstalleerd zijn. De business connector DLL in de client bin bevestigt dit verhaal:

    Version 4.0.2503.1872.

Middels een simpele info in een portal webform kreeg ik echter een andere versie:

    Kernel version: 4.0.2163.0

Runtime was de versie dus 4.0.2163.0 (SP1). In de GAC (Global Asembly Cache) was inderdaad een andere DLL geïnstalleerd:

Oplossing was simpel: opnieuw registeren van de DLL in de client bin map. Maar deze productie server had geen powerhell of .NET SDK toolkit (gacutil.exe) om een DLL te registreren. Daarop heb ik tijdelijk even de toolkit van mijn laptop (Windows 10) gekopieerd naar de server::
C:\Program Files (x86)\Microsoft SDKs\Windows

Er zijn 3 mappen: gacutil zit in 2 van deze mappen(v7.0a en v8.0a). Gebruik hier de v7.0a, bij de v8.0a krijg je een melding: :
entry point was not found
De volgende DLL's heb ik geregistreerd:
  • C:\Program Files\Microsoft Dynamics AX\40\Client\Bin\Microsoft.Dynamics.BusinessConnectorNet.dll
  • C:\Program Files\Microsoft Dynamics AX\40\Client\Bin\Microsoft.Dynamics.ClrBridge.dll
  • C:\Program Files\Microsoft Dynamics AX\40\Client\Bin\NL\Microsoft.Dynamics.BusinessConnectorNet.resources.dll
En nu is de portal het met mij eens over welke versie er is:

En de PDF wordt weer juist gegenereerd.