Jump to content

Fastest run-time start-up with minimal usage of OS, CPU, memory


Recommended Posts

Hi folks - I have to install a Labview program on a product's embedded Windows 10 computer that at this time has zero NI software on it. The program needs to run immediately after computer boot-up, do its thing in under a minute, and then quit. I really need this program to start running as quickly as possible, and then after quitting leave nothing NI-related running. Do any of you have experience with this kind of situation? Are there any INI file settings or other configurations that will make LabVIEW Run-Time and NI-VISA run with minimal overhead and minimal sub-processes? For example, I don't want any NI processes to look for network connectivity at all nor attempt to "phone home". Also, after quitting I could halt specific processes and services that NI has left running.

Thanks very much,  -Joe

 

Link to comment

Hi Joe,

First of all, I would use Task Scheduler to configure your executable to run once at startup, with "highest priority". You can also experiment with the setting "run whether user is logged on or not" and with running it in the account "NT AUTHORITY\SYSTEM": I think that this will allow your task to run before Windows logs you in as a user. You will also want to get rid of most unnecessary tasks in Task Scheduler, disable unnecessary services (including NI services), and minimize the number of logs that Windows creates. Also you'll want to check the configuration of your BIOS/UEFI: minimize startup delays, power-on self-tests, disable unused hardware (e.g. unused COM ports).

You mentioned LV runtime engine and VISA. I don't know what hardware you control through VISA, but if it's an RS232 instrument and if you can use a USB/COM adapter, and if your adapter could be built using an FTDI chip, then you don't need VISA: you can use in FTDI driver. I can share a LV wrapper for this driver. No guarantee that this approach is faster than VISA, but it could be worth trying.

One more idea: if your application is really light, you may want to consider an older version of LV, maybe as old as LV6 or LV7.11: they can work without runtime engines installed, all you'll need is a few DLLs. Fewer things to load from the drive and fewer services to worry about after your application exits.

Finally, you used the word "embedded". I don't know if you just mean a physically embedded PC running regular commercial Windows or a truly customized version of Windows, like Windows 10 Enterprise LTSC. If it's the latter, there are lots of things that you can customize in it, including throwing out most things that you don't need, enabling keyboard filter (e.g. to block Ctrl-Alt-Del), universal write filter (UWF) to block writes to the hard drive (this can also speed up the process, since your disk writes will actually go to a dedicated part of RAM). To learn more about using Windows 10 LTSC for building a "kiosk"-type application, check out https://solidusintegration.com/sikiosk.html.

Best,

Sergey

Edited by Sergey L
  • Thanks 1
Link to comment

Hi Sergey - Thank you very much for the really helpful reply!  That is a lot of good advice.  I have some work to do.  We do disable much Windows functionality using their "policy" editor.  I didn't think of the NI Services that are enabled to start up with the system.  I just looked at those:

image.png.c9bcf776490339a9462c4f59646f299a.png

I'll experiment with how much of this I can disable and still have LabVIEW Run-Time execute properly!

Good point about NI-VISA.  Upon review, yes I am only using it for RS232 communication for this particular project.  Thanks for mentioning the FTDI driver.  You made me remember also the .NET SerialPort class that already resides in Windows.  I just now wired up a few functions to remind myself how that class works:

image.png.585ebe659bc285bb2e031997d2a9c83f.png

 

Thanks again,   -Joe

 

Link to comment

Some ideas:

Create an installer including the runtime engine and select only the components you really need.

Instead of the .NET for serial communication, you can use the lvserial driver. Basically it is a DLL calling the windows API with a minimal footprint. The labview API is very similar to what you know from VISA.

  • Like 1
  • Thanks 1
Link to comment

Hello Martin, thanks very much!  Back in 2008 I ceased the practice of including LabVIEW Run-Time (and other drivers) in my app installer, and have been installing those separately.  I forgot about the run-time components selection, thanks for pointing that out, I'll try that.  For the app today, I don't need any of the checked subcomponents below.

image.png.bb0ffd32c3f0d76d9592e4ecfd1d3501.png

Thanks for the link to your lvserial driver package.  Brings back pre-VISA memories!

-Joe

Link to comment
  • 1 year later...
52 minutes ago, viSci said:

Does lvserial acutally support regex termination strings?  How is that accomplished?

It's utilizing the PCRE library, that is incorporated into the code. It's a first incarnation of PCRE, 8.35 for a 32-bit lvserial.dll and 8.45 for a 64-bit one. When configuring the serial port, you can choose between four variants of the termination:

/*  CommTermination2
 *
 *  Configures the termiation characters for the serial port.
 *
 *  parameter
 *		hComm				serial port handle
 *		lTerminationMode	specifies the termination mode, this can be one of the
 *							following value:
 *								COMM_TERM_NONE		no termination
 *								COMM_TERM_CHAR		one or more termination characters
 *								COMM_TERM_STRING	a single termination string
 *								COMM_TERM_REGEX		a regular expression
 *		pcTermination		buffer containing the termination characters or string
 *		lNumberOfTermChar	number of characters in pcTermination
 *		
 *  return
 *		error code
 */

Now when you read the data from the port (lvCommRead -> CommRead function), it works this way:

	//if any of the termination modes are enabled, we should take care
	//of that. Otherwise, we can issue a single read operation (see below)
	if (pComm->lTeminationMode != COMM_TERM_NONE)
	{
		//Read one character after each other and test for termination.
		//So for each of these read operation we have to recalculate the
		//remaining total timeout.
		
		Finish = clock() +
			pComm->ulReadTotalTimeoutMultiplier*ulBytesToRead +
			pComm->ulReadTotalTimeoutConstant;

		//nothing received: initialize fTermReceived flag to false
		fTermReceived = FALSE;

		//read one byte after each other and test the termination
		//condition. This continues until the termination condition
		//matches, the maximum number bytes are received or an if 
		//error occurred.
		do {
			//only for this iteration: no bytes received.
			ulBytesRead = 0;

			//calculate the remaining time out
			ulRemainingTime = Finish - clock();

			//read one byte from the serial port
			lFnkRes = __CommRead(
				pComm, 
				pcBuffer+ulTotalBytesRead, 
				1, 
				&ulBytesRead, 
				osReader,
				ulRemainingTime);
			
			//if we received a byte, we shold update the total number of 
			//received bytes and test the termination condition.
			if (ulBytesRead > 0)
			{
				//update the total number of received bytes
				ulTotalBytesRead += ulBytesRead;

				//test the termination condition
				switch (pComm->lTeminationMode)
				{
					case COMM_TERM_CHAR: //one or more termination characters
						//search the received character in the buffer of the
						//termination characters.
						fTermReceived = 
							memchr(					
								pComm->pcTermination, 
								*(pcBuffer+ulTotalBytesRead-1), 
								pComm->lNumberOfTermChar) != NULL;
						break;

					case COMM_TERM_STRING: //termination string
						//there must be at least the number of bytes of 
						//the termination string.
						if (ulTotalBytesRead >= (unsigned long)pComm->lNumberOfTermChar)
						{
							//we only test the last bytes of the receive buffer
							fTermReceived = memcmp(
								pcBuffer + ulTotalBytesRead - pComm->lNumberOfTermChar,
								pComm->pcTermination, 
								pComm->lNumberOfTermChar) == 0;
						}
						break;

					case COMM_TERM_REGEX: //regular expression
						//execute the precompiled regular expression
						fTermReceived = pcre_exec(
							pComm->RegEx, 
							pComm->RegExExtra,
							pcBuffer, 
							ulTotalBytesRead, 
							0,
							PCRE_NOTEMPTY,
							aiOffsets,
							3) >= 0;
						break;

					default:
						//huh ... unknown termination mode
						_ASSERT(0);
						fTermReceived = 1;
				}
			}
					  
			//Repeat this until 
			// - an error occurred or
			// - the termination condition is true or 
			// - we timed out
		} while (!lFnkRes && 
				!fTermReceived &&
				ulTotalBytesRead < ulBytesToRead &&
				Finish > clock());

		//adjust the result code according to the result of 
		//the read operation.
		if (lFnkRes == COMM_SUCCESS)
		{
			if (!fTermReceived)
			{
				//termination condition not matched, so we test, if the max
				//number of bytes are received.
				if (ulTotalBytesRead == ulBytesToRead)
					lFnkRes = COMM_WARN_NYBTES;
				else
					lFnkRes = COMM_ERR_TERMCHAR;
			}			
			else
				//termination condition matched
				lFnkRes = COMM_WARN_TERMCHAR;
		}
	}
	else
	{
		//The termination is not activated. So we can read all
		//requested bytes in a single step.
		lFnkRes = __CommRead(
			pComm, 
			pcBuffer, 
			ulBytesToRead, 
			&ulTotalBytesRead, 
			osReader,
			pComm->ulReadTotalTimeoutMultiplier*ulBytesToRead +
				pComm->ulReadTotalTimeoutConstant
		);
	}

 

1 hour ago, viSci said:

Is that capability built into an interrupt service routine or is it just simulated in a polling loop under the hood?

As shown in the code above, when the termination is activated, the library reads data one byte at a time in a do ... while loop and tests it against the term char / string / regular expression on every iteration. I can't say how good that PCRE engine is as I never really used it.

Link to comment

How far from the goal are you now, and have you identified where the time is spent?

If you e.g. just manually launch the LabVIEW application and flag when it does its first action, how much of the minute is spent already and how much time does the rest of its tasks use? You say you want the program to be launched by Windows as quickly as possible too, how much time does it take for Windows to launch it now compared to any other simple application/service you can set up?

Link to comment
On 8/19/2022 at 3:44 PM, AutoMeasure said:

Hello Martin, thanks very much!  Back in 2008 I ceased the practice of including LabVIEW Run-Time (and other drivers) in my app installer, and have been installing those separately.  I forgot about the run-time components selection, thanks for pointing that out, I'll try that.  For the app today, I don't need any of the checked subcomponents below.

image.png.bb0ffd32c3f0d76d9592e4ecfd1d3501.png

You actually will need the NI VC2015 Runtime or another compatible Microsoft Visual C Runtime. Since the Visual C Runtime 2015 and higher is actually backwards compatible, it is indeed not strictly needed for Windows 10 or 11 based systems since they generally come with a newer one. However that is not guaranteed. If your Windows 10 system is not meticulously updated, it may have an older version of this Runtime Library installed than your current LabVIEW 2021 installation requires. And that will not work, it's only backwards compatible, meaning a newer installed version can be used by an application compiled towards an older version, not the other way around. You mentioning that the system will be an embedded system makes me think that it is neither a state of the art latest release, not that it will be regularly updated.

  • Thanks 1
Link to comment
On 11/12/2023 at 4:00 PM, dadreamer said:

As shown in the code above, when the termination is activated, the library reads data one byte at a time in a do ... while loop and tests it against the term char / string / regular expression on every iteration. I can't say how good that PCRE engine is as I never really used it.

It's the same that LabVIEW adopted many years ago when they added the PCRE function to the string palette in addition to their own older Match Pattern function that was obviously Perl inspired (and likely generated with Bison Yacc), but more limited (not necessarily a bad thing, PCRE is a real beast to tame 😀). Not sure about the exact version used in LabVIEW but since it appeared around LabVIEW 8.0 I think, it would be likely version 6.0 or maybe 5.0, although I'm sure they upgraded that in the meantime to a newer version and maybe even PCRE2.

Edited by Rolf Kalbermatter
Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.