none
ngen static variable initialization RRS feed

  • Question

  • Hi,   When running without ngen creating a new instance of a class automatically initializes all static variables of the class, how can I make ngen do the same thing?   What is the best work-around?   Thanks,Mark

     

    • Moved by Larcolais Gong Wednesday, August 10, 2011 7:32 AM (From:Visual C# General)
    Tuesday, August 9, 2011 9:27 AM

Answers

  • This has nothing to do with NGEN failing to load the correct assemblies. Instead the difference in NGEN timing appears to be caused by http://csharpindepth.com/Articles/General/Beforefieldinit.aspx. Adding an empty static constructor removes the implicit TypeAttributes.BeforeFieldInit and defines the execution sequence to that both NGEN and IL work.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    
    namespace StaticInit
    {
      class Program
      {
        class staticTest
        {
          public staticTest()
          {
            //Trace.WriteLine(staticVar.i);
          }
          static staticTest() { }
    
          public class staticLoader
          {
            public static List<staticLoader> staticLoaders = new List<staticLoader>();
            public int i;
            public staticLoader(int i)
            {
              this.i = i;
              staticLoaders.Add(this);
            }
          }
          static staticLoader staticVar = new staticLoader(0);
        }
        static void Main(string[] args)
        {
          new staticTest();
          Console.WriteLine("Static Load " + ((staticTest.staticLoader.staticLoaders.Count == 1 ) ? "Succeded" : "Failed"));
        }
      }
    }
    
    

    $ngen install staticinit.exe
    Microsoft (R) CLR Native Image Generator - Version 4.0.30319.1
    Copyright (c) Microsoft Corporation.  All rights reserved.
    Installing assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\StaticIn
    it\StaticInit\bin\Debug\staticinit.exe
    1>    Compiling assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\Sta
    ticInit\StaticInit\bin\Debug\staticinit.exe (CLR v4.0.30319) ...
    1>StaticInit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <debug>

    $staticinit
    Static Load Succeded

    $

    • Marked as answer by eryang Friday, September 9, 2011 3:13 AM
    Tuesday, August 23, 2011 12:45 AM

All replies

  • It should behave all the same weather ngen'ed or not. Can you describe how to reproduce this?

    Tuesday, August 9, 2011 9:41 AM
    Moderator
  • using System;
    using System.Diagnostics;
    
    
    
    The below module was converted from a Data General Macro Assembler language named CAPS 
    
    namespace eV
    {
      /// <summary>
      /// Summary Description for ArmyICNR.
      /// </summary>
      public class ArmyCmd3
      {
        public ArmyCmd3()
        {
          // if the line below low is missing ngen will not initialize the below static eV.capsCommands when calling this constructor, 
          // running the IL code will
          Trace.WriteLine(CI_CMD.description);
        }
    
        public static eV.capsCommand AJ_CMD = new eV.capsCommand("Abort Print Job", "AJ", 1, new invokeDelegate(AJ_CMDInvoke), 7, 8);
        static int AJ_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____9, c.ST_JOB); //Set job status to job aborted by op
          c.INCLD(ArmyCmd3.ABJOB);
          return 0;
          // ENDCMD
        }
        public static eV.capsDoc ABJOB = new eV.capsDoc(null, new invokeDelegate(ABJOBInvoke), null);
        public static int ABJOBInvoke(caps cps)
        {
          c.disablePpv = true;
          if (B.COND(p.pc.EQ, c.ST_JOB, c.A____7) || B.COND(p.pc.EQ, c.ST_JOB, c.A____8) || B.COND(p.pc.EQ, c.ST_JOB, c.A____0) || B.COND(p.pc.EQ, c.ST_JOB, c.A____Z))
          {
    
          }
          else
            if (c.P2)
            {
              LB.F_MOV(c.A____9, c.ST_JOB); //Set job status to job aborted by op
              if (B.COND(p.pc.NZ, c.RP_cNT))
                c.PRLOG(ArmyDoc4.S_RPT);
            }  //Job not ended by operator
          cp_asy.CALLX(p.pc.PRO, new PCP(new capsDelegate(RESLC.ab_job)));
          return 0;
          // ENDDOC
        }
    
        public static eV.capsCommand CP_CMD = new eV.capsCommand("Copy Program to EagleVision PC", "CP", 1, new invokeDelegate(CP_CMDInvoke), ckmenu.screenSystemManager);
        static int CP_CMDInvoke(caps cps)
        {
          cp_asy.CALLX(p.pc.PRO, new PCP(new capsDelegate(cd.cd_cpy)));
          return 0;
          ;
          // ENDCMD
        }
    
        public static eV.capsCommand SP_CMD = new eV.capsCommand("System Parameter Maintenance", "SP", 2, new invokeDelegate(SP_CMDInvoke), ckmenu.screenSystemManager);
        static int SP_CMDInvoke(caps cps)
        {
          ArmyCmd1.MENUC(ckmenu.screenSystemParameter); // 11
          return 0;
          // ENDCMD
        }
    #if false
    
    		public static eV.capsCommand SO_CMD=new eV.capsCommand( "SO",0,new invokeDelegate(SO_CMDInvoke),MENUL);
    		static int SO_CMDInvoke(caps cps) 
    		{
    			,"Display System Operations" 
    				 c.MENUL(1,9) ; 
    			ArmyCmd1.MENUC(ckmenu.screenSystemOperations) ; 
    			// ENDCMD
    		} 
    #endif
    
        public static eV.capsCommand CS_CMD = new eV.capsCommand("Change Subtotal Break Frequency", "CS", 2, new invokeDelegate(CS_CMDInvoke), new VCOND(VCOND.estate.Null, p.pc.EQ, c.ST_fRQ, c.ST_fRQ), ckmenu.screenSystemParameter);
        static int CS_CMDInvoke(caps cps)
        {
    
          screen.DSPLY(03, 27, "Subtotal Break Frequency");
          screen.PRMPT(09, 24, "Subtotal break frequency:");
          dsp.INPUT(09, 51, c.ST_fRQ, ed.RJZ);
          dsp.INPOK(13, 24, "Frequency correct (Y or N):");
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand ES_CMD = new eV.capsCommand("Change Emergency Subtotal Break Frequency", "ES", 2, new invokeDelegate(ES_CMDInvoke), new VCOND(VCOND.estate.Null, p.pc.EQ, c.EM_fRQ, c.EM_fRQ), ckmenu.screenSystemParameter);
        static int ES_CMDInvoke(caps cps)
        {
          screen.DSPLY(03, 27, "Emergency Subtotal Break Frequency");
          screen.PRMPT(09, 24, "Emergency Subtotal break frequency:");
          dsp.INPUT(09, 62, c.EM_fRQ, ed.RJZ);
          dsp.INPOK(13, 24, "Frequency correct (Y or N):");
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand DP_CMD = new eV.capsCommand("Disable Post Print Verification", "DP", 2, new invokeDelegate(DP_CMDInvoke), new VCOND(VCOND.estate.Enabled, p.pc.EQ, c.EBLPPV, c.A____Y), ckmenu.screenSystemParameter);
        static int DP_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____N, c.EBLPPV); //Set PPV enabled flag to no
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand EP_CMD = new eV.capsCommand("Enable Post Print Verification", "EP", 2, new invokeDelegate(EP_CMDInvoke), new VCOND(VCOND.estate.Disabled, p.pc.EQ, c.EBLPPV, c.A____Y), ckmenu.screenSystemParameter);
        static int EP_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____Y, c.EBLPPV); //Set PPV enabled flag to yes
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand DD_CMD = new eV.capsCommand("Disable Debugging", "DD", 2, new invokeDelegate(DD_CMDInvoke), new VCOND(VCOND.estate.Enabled, p.pc.EQ, c.debugging, c.A____Y), ckmenu.screenSystemParameter);
        static int DD_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____N, c.debugging); //Set retry reporting flag to no
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand ED_CMD = new eV.capsCommand("Enable Debugging", "ED", 2, new invokeDelegate(ER_CMDInvoke), new VCOND(VCOND.estate.Disabled, p.pc.EQ, c.debugging, c.A____Y), ckmenu.screenSystemParameter);
        static int ER_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____Y, c.debugging); //Set retry reporting flag to yes
          return 0;
          // ENDCMD
        }
    #if thereWereRetrys
    		public static eV.capsCommand DR_CMD=new eV.capsCommand("Disable PPV Retry Reporting","DR",2,new invokeDelegate(DR_CMDInvoke),new VCOND(VCOND.estate.Enabled,p.pc.EQ,c.RT_fLG,c.A____Y),ckmenu.screenSystemParameter);
    		static int DR_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____N,ref c.RT_fLG ) ; //Set retry reporting flag to no
    			return 0;
    			// ENDCMD
    		} 
    
    		public static eV.capsCommand ER_CMD=new eV.capsCommand("Enable PPV Retry Reporting","ER",2,new invokeDelegate(ER_CMDInvoke),new VCOND(VCOND.estate.Disabled,p.pc.EQ,c.RT_fLG,c.A____Y),ckmenu.screenSystemParameter);
    		static int ER_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____Y,ref c.RT_fLG ) ; //Set retry reporting flag to yes
    			return 0;
    			// ENDCMD
    		} 
    #endif
    #if false
    		public static eV.capsCommand DB_CMD=new eV.capsCommand("Disable Barcode Printer","DB",2,new invokeDelegate(DB_CMDInvoke),ckmenu.screenSystemParameter);
    		static int DB_CMDInvoke(caps cps) 
    		{
    			, 
    				 11(3,11) ; 
    			new VCOND(VCOND.estate.Enabled,p.pc.NE,c.BC_STS,c.A____5) ; 
    			LB.F_MOV(c.A____5,c.BC_STS ) ;
    			LB.F_MOV(c.A____Y,c.BC_DIS ) ; //Set "Permanent" Flag
    			// ENDCMD
    		} 
    
    		public static eV.capsCommand EB_CMD=new eV.capsCommand( "EB",2,new invokeDelegate(EB_CMDInvoke),ckmenu.screenSystemParameter);
    		static int EB_CMDInvoke(caps cps) 
    		{
    			,"Enable Barcode Printer" 
    				 11(3,11) ; 
    			new VCOND(VCOND.estate.Disabled,p.pc.NE,c.BC_DIS,c.A____N) ; 
    			LB.F_MOV(c.A____0,c.BC_STS ) ;
    			LB.F_MOV(c.A____N,c.BC_DIS ) ; //Clear "Permanent" Flag
    			// ENDCMD
    		}
    #endif
    
        public static eV.capsCommand DA_CMD = new eV.capsCommand("Disable Operator Document Remake", "DA", 2, new invokeDelegate(DA_CMDInvoke), new VCOND(VCOND.estate.Enabled, p.pc.EQ, c.EBLRMK, c.A____Y), ckmenu.screenSystemParameter);
        static int DA_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____N, c.EBLRMK); //Set auto remake flag to no
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand EA_CMD = new eV.capsCommand("Enable Operator Document Remake", "EA", 2, new invokeDelegate(EA_CMDInvoke), new VCOND(VCOND.estate.Disabled, p.pc.EQ, c.EBLRMK, c.A____Y), ckmenu.screenSystemParameter);
        static int EA_CMDInvoke(caps cps)
        {
          LB.F_MOV(c.A____Y, c.EBLRMK); //Set auto remake flag to yes
          return 0;
          // ENDCMD
        }
    
        public static eV.capsCommand CV_CMD = new eV.capsCommand("Change End-of-Job Void Count", "CV", 2, new invokeDelegate(CV_CMDInvoke), new VCOND(VCOND.estate.Null, p.pc.EQ, c.VD_sTR, (string)c.VD_sTR), ckmenu.screenSystemParameter);
        static int CV_CMDInvoke(caps cps)
        {
          screen.DSPLY(03, 27, "Void Count");
          screen.PRMPT(09, 24, "Void Count:");
          if (c.P2)
          {
            dsp.INPUT(09, 36, c.VD_sTR, ed.RJZ);
            LB.F_MOV(c.VD_sTR, c.VD_cNT); //Move into # and string parts
            if (B.COND(p.pc.GT, c.VD_cNT, m1.minVoidPairs))
            { //If number makes any sense
              LInt.Count(c.VD_cNT, -m1.minVoidPairs);
              LB.F_MOV(c.VD_cNT, c.VD_cNT, ed.RJZ); //. Move number part to string
            }
            else
            {
              LB.F_MOV(c.A_0001, c.VD_cNT);
              LB.F_MOV(m1.minVoidPairs, c.VD_sTR);
            }  //End-IF
            dsp.INPOK(13, 24, "Count correct (Y or N):");
          }
          return 0;
          // ENDCMD
        }
        public static eV.capsCommand CI_CMD = new eV.capsCommand("Change Number of EOJ Void ICNs", "CI", 2, new invokeDelegate(CI_CMDInvoke), new VCOND(VCOND.estate.Null, p.pc.EQ, c.VDIsTR, c.VDIsTR), ckmenu.screenSystemParameter);
        static int CI_CMDInvoke(caps cps)
        {
          screen.DSPLY(03, 27, "ICN Void Count");
          screen.PRMPT(09, 24, "ICN Void Count:");
          if (c.P2)
          {
            dsp.INPUT(09, 40, c.VDIsTR, ed.RJZ);
            LB.F_MOV(c.VDIsTR, c.VDIcNT); //Move into # and string parts
            if (B.COND(p.pc.LT, c.VDIcNT, c.A____1))
            { //If number doesn't make sense
              LB.F_MOV(c.A_0006, c.VDIcNT);
              LB.F_MOV(c.VDIcNT, c.VDIcNT, ed.RJZ); //. Move number part to string
            }  //End-IF
            dsp.INPOK(13, 24, "Count correct (Y or N):");
          }
          return 0;
          // ENDCMD
        }
    #if false
    		public static eV.capsCommand DB_CMD=new eV.capsCommand("Disable Printer Buffer and Loop Control","DB",2,new invokeDelegate(DB_CMDInvoke),new VCOND(VCOND.estate.Enabled,p.pc.EQ,c.EBLBCT,c.A____Y),ckmenu.screenSystemParameter);
    		static int DB_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____N,c.EBLRMK ) ; //Set auto remake flag to no
    			return 0;
    			// ENDCMD
    		} 
    
    		public static eV.capsCommand EB_CMD=new eV.capsCommand("Enable Printer Buffer and Loop Control","EB",2,new invokeDelegate(EB_CMDInvoke),new VCOND(VCOND.estate.Disabled,p.pc.EQ,c.EBLBCT,c.A____Y),ckmenu.screenSystemParameter);
    		static int EB_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____Y,c.EBLRMK ) ; //Set auto remake flag to yes
    			return 0;
    			// ENDCMD
    		} 
    		public static eV.capsCommand DR_CMD=new eV.capsCommand("Disable Reverse Printing","DR",2,new invokeDelegate(DB_CMDInvoke),new VCOND(VCOND.estate.Enabled,p.pc.EQ,c.reverseLs,c.A____Y),ckmenu.screenSystemParameter);
    		static int DB_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____N,c.reverseLs ); // printed in order
    			return 0;
    			// ENDCMD
    		} 
    
    		public static eV.capsCommand ER_CMD=new eV.capsCommand("Enable Reverse Printing","ER",2,new invokeDelegate(EB_CMDInvoke),new VCOND(VCOND.estate.Disabled,p.pc.EQ,c.reverseLs,c.A____Y),ckmenu.screenSystemParameter);
    		static int EB_CMDInvoke(caps cps) 
    		{
    			LB.F_MOV(c.A____Y,c.reverseLs ) ; //Set auto remake flag to yes
    			return 0;
    			// ENDCMD
    		} 
    #endif
    
    
      } // class ArmyCmd3
    } // namespace eV
    
    

    Tuesday, August 9, 2011 11:19 PM
  • Hi,   When running without ngen creating a new instance of a class automatically initializes all static variables of the class, how can I make ngen do the same thing?   What is the best work-around?   Thanks,Mark

     


    I do not understand your question.  NGEN does not execute code, so it cannot create an instance of an object.  Only the CLR executes the compiled code.  Once you run NGEN, you start the application as you normally would.  NGEN simply saves the CLR the task of running the JIT Compiler on your assemblies as they are demand loaded.

    Rudy   =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://thesharpercoder.blogspot.com/

    • Marked as answer by eryang Monday, August 22, 2011 8:01 AM
    • Unmarked as answer by eryang Tuesday, August 23, 2011 1:40 AM
    Tuesday, August 9, 2011 11:43 PM
  • I moved your thread into CLR forum for further support.

    Thanks,


    Larcolais Gong[MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Wednesday, August 10, 2011 7:32 AM
  • As Rudedog2 said, NGen.exe just generate a native image from a .net assembly, it does not execute code inside the assembly.
    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, August 16, 2011 3:10 AM
  • Hi Mark,

    Task of NGen is just to create compiled version of your code files, which can be further used by runtime(JIT need not to recompile your files, as native code is already generated by NGen). It has nothing to do with code execution.


    Regards, http://shwetamannjain.blogspot.com
    Tuesday, August 16, 2011 3:32 AM
  •  This simple example shows that NGen code runs differently.
    
    using System;
    using System.Collections.Generic;
    
    namespace StaticInit
    {
     class Program
     {
      class staticTest
      {
       public staticTest()
       {
       }
       public class staticLoader
       {
        public static List<staticLoader> staticLoaders = new List<staticLoader>();
        int i;
        public staticLoader(int i)
        {
         this.i = i;
         staticLoaders.Add(this);
        }
       }
       static staticLoader staticVar = new staticLoader(0);
      }
      static void Main(string[] args)
      {
       new staticTest();
       Console.WriteLine("Static Load " + ((staticTest.staticLoader.staticLoaders.Count == 1 ) ? "Succeded" : "Failed"));
      }
     }
    }
    
    

    This is the log


    $staticinit
    Static Load Succeded

    $ngen install staticinit.exe
    Microsoft (R) CLR Native Image Generator - Version 4.0.30319.1
    Copyright (c) Microsoft Corporation.  All rights reserved.
    Installing assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\StaticIn
    it\StaticInit\bin\Debug\staticinit.exe
    1>    Compiling assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\Sta
    ticInit\StaticInit\bin\Debug\staticinit.exe (CLR v4.0.30319) ...
    1>StaticInit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <debug>

    $staticinit
    Static Load Failed

    $ngen uninstall staticinit.exe
    Microsoft (R) CLR Native Image Generator - Version 4.0.30319.1
    Copyright (c) Microsoft Corporation.  All rights reserved.
    Uninstalling assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\Static
    Init\StaticInit\bin\Debug\staticinit.exe

    $staticinit
    Static Load Succeded

    $

    Before creating the NGen image the program runs, after installing it fails, after uninstalling it runs,   This has been tested in both Windows XP SP3 and Windows 7 PCs.


    Monday, August 22, 2011 9:51 PM
  • Even though NGEN saves the CLR the chore of compiling the asssemblies, the CLR still requires that the assemblies be present.

    Rudy  =8^D


    Mark the best replies as answers. "Fooling computers since 1971."

    http://thesharpercoder.blogspot.com/

    Monday, August 22, 2011 10:05 PM
  • This has nothing to do with NGEN failing to load the correct assemblies. Instead the difference in NGEN timing appears to be caused by http://csharpindepth.com/Articles/General/Beforefieldinit.aspx. Adding an empty static constructor removes the implicit TypeAttributes.BeforeFieldInit and defines the execution sequence to that both NGEN and IL work.

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    
    namespace StaticInit
    {
      class Program
      {
        class staticTest
        {
          public staticTest()
          {
            //Trace.WriteLine(staticVar.i);
          }
          static staticTest() { }
    
          public class staticLoader
          {
            public static List<staticLoader> staticLoaders = new List<staticLoader>();
            public int i;
            public staticLoader(int i)
            {
              this.i = i;
              staticLoaders.Add(this);
            }
          }
          static staticLoader staticVar = new staticLoader(0);
        }
        static void Main(string[] args)
        {
          new staticTest();
          Console.WriteLine("Static Load " + ((staticTest.staticLoader.staticLoaders.Count == 1 ) ? "Succeded" : "Failed"));
        }
      }
    }
    
    

    $ngen install staticinit.exe
    Microsoft (R) CLR Native Image Generator - Version 4.0.30319.1
    Copyright (c) Microsoft Corporation.  All rights reserved.
    Installing assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\StaticIn
    it\StaticInit\bin\Debug\staticinit.exe
    1>    Compiling assembly C:\Users\Mark\Documents\Visual Studio 2010\Projects\Sta
    ticInit\StaticInit\bin\Debug\staticinit.exe (CLR v4.0.30319) ...
    1>StaticInit, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null <debug>

    $staticinit
    Static Load Succeded

    $

    • Marked as answer by eryang Friday, September 9, 2011 3:13 AM
    Tuesday, August 23, 2011 12:45 AM
  • Indeed, for the BeforeFieldInit semantic, seems JIT (or Ngen) uses the rule in CLI Specification:

     

    If marked BeforeFieldInit then the type's initializer method is executed at, or sometime before, first access to any static field defined for that type

     

    In your previous code snippet, no static field of staticTest class is accessed, so Ngen doesn't break the rule, even though native image (ngened) gives different output against the assembly (not-ngened).


    Eric Yang [MSFT]
    MSDN Community Support | Feedback to us
    Get or Request Code Sample from Microsoft
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Tuesday, August 23, 2011 6:40 AM
  • I am going through my code to put static constructors into all classes with instance constructors and any initialized static variables. That way the static initialization execution sequence is speced and tested to be before any instance constructors whether or not ngen is run. Thanks, Mark
    Friday, September 9, 2011 10:59 AM