Jump to content

Sky Slate Blueberry Blackcurrant Watermelon Strawberry Orange Banana Apple Emerald Chocolate
Photo

A_LoopFileLongPath MUCH slower than A_LoopFileFullPath


  • Please log in to reply
4 replies to this topic
flashkid
  • Members
  • 115 posts
  • Last active: Apr 12 2013 06:33 PM
  • Joined: 25 Aug 2007
Today, I've found out, that the use of A_LoopFileLongPath is much slower than using A_LoopFileFullPath.
Compare:
SetBatchLines, -1
A := A_TickCount
Loop, C:\*.*,,1
	List .= A_LoopFileLongPath
B := A_TickCount
MsgBox % (B-A) / 1000

A := A_TickCount
Loop, C:\*.*,,1
	List .= A_LoopFileFullPath
B := A_TickCount
MsgBox % (B-A) / 1000
I got ~55 secs for LongPath and only 4 secs for FullPath.

Where does this difference come from?
Regards, flashkid

jaco0646
  • Moderators
  • 3165 posts
  • Last active: Apr 01 2014 01:46 AM
  • Joined: 07 Oct 2006
Listed in the Help file are the three extra tasks A_LoopFileLongPath performs, which A_LoopFileFullPath does not. Thus, it takes more time.

flashkid
  • Members
  • 115 posts
  • Last active: Apr 12 2013 06:33 PM
  • Joined: 25 Aug 2007
Ok thanks, I've read that, but haven't thought that it would made such a big difference :)

jballi
  • Members
  • 1029 posts
  • Last active:
  • Joined: 01 Oct 2005
At first I thought this was a fluke of file system caching but after running a series of tests using a modified version of this script, the results were clear. A_LoopFileLongPath is significantly slower than A_LoopFileFullPath. How much faster is A_LoopFileFullPath? With the test using the basic format as defined by flashkid, at least 18 times faster. If the concatenation statement is converted to a simple assignment statement, more than 26 times faster. Your results will vary.

Of course I will continue to use A_LoopFileLongPath when needed but I will no longer use it by default. Thanks for the tip. :D

sinkfaze
  • Moderators
  • 6367 posts
  • Last active: Nov 30 2018 08:50 PM
  • Joined: 18 Mar 2008
If you want to get an idea of what exactly is going on, here's the source for both A_LoopFileFullPath and A_LoopFileLongPath and some notes of interest:

[color=black]VarSizeType BIV_LoopFileFullPath(char *aBuf, char *aVarName)[/color]
{
	[color=green]// The loop handler already prepended the script's directory in cFileName for us:[/color]
	char *full_path = g->mLoopFile ? g->mLoopFile->cFileName : "";
	if (aBuf)
		strcpy(aBuf, full_path);
	return (VarSizeType)strlen(full_path);
}

[color=black]VarSizeType BIV_LoopFileLongPath(char *aBuf, char *aVarName)[/color]
{
	char *unused, buf[MAX_PATH] = ""; [color=green]// Set default.[/color]
	if (g->mLoopFile)
	{
		[color=green]// GetFullPathName() is done in addition to ConvertFilespecToCorrectCase() for the following reasons:
		// 1) It's currrently the only easy way to get the full path of the directory in which a file resides.
		//    For example, if a script is passed a filename via command line parameter, that file could be
		//    either an absolute path or a relative path.  If relative, of course it's relative to A_WorkingDir.
		//    The problem is, the script would have to manually detect this, which would probably take several
		//    extra steps.
		// 2) A_LoopFileLongPath is mostly intended for the following cases, and in all of them it seems
		//    preferable to have the full/absolute path rather than the relative path:
		//    a) Files dragged onto a .ahk script when the drag-and-drop option has been enabled via the Installer.
		//    b) Files passed into the script via command line.
		// The below also serves to make a copy because changing the original would yield
		// unexpected/inconsistent results in a script that retrieves the A_LoopFileFullPath
		// but only conditionally retrieves A_LoopFileLongPath.[/color]
		if (!GetFullPathName(g->mLoopFile->cFileName, MAX_PATH, buf, &unused))
			*buf = '\0';[color=green] // It might fail if NtfsDisable8dot3NameCreation is turned on in the registry, and possibly for other reasons.[/color]
		else
			[color=green]// The below is called in case the loop is being used to convert filename specs that were passed
			// in from the command line, which thus might not be the proper case (at least in the path
			// portion of the filespec), as shown in the file system:[/color]
			ConvertFilespecToCorrectCase(buf);
	}
	if (aBuf)
		strcpy(aBuf, buf); [color=green]// v1.0.47: Must be done as a separate copy because passing a size of MAX_PATH for aBuf can crash when aBuf is actually smaller than that (even though it's large enough to hold the string). This is true for ReadRegString()'s API call and may be true for other API calls like the one here.[/color]
	return (VarSizeType)strlen(buf); [color=green]// Must explicitly calculate the length rather than using the return value from GetFullPathName(), because ConvertFilespecToCorrectCase() expands 8.3 path components.[/color]
}