Search code examples
fileparallel-processingimpersonationcopying

Why impersonated Parallel function performs slow on the first run but speeds up subsequently?


So I have some code which copies files to 5 remote PCs on the network. I have a class which impersonates the methods who logon is required

''' <summary>
''' Returns the names of the files including their path that match the regex pattern found in this directory. 
''' </summary>
''' <param name="searchOption">
''' The parameter option SearchOption.AllDirectories indicates that the search should include the current directory and any subdirectories
''' The parameter option SearchOption.TopDirectoryOnly indicates that the search should only include the current directory. 
''' </param> 
Public Function GetFileContent(filePath As String, searchPattern As String, Optional searchOption As SearchOption = Nothing) As String() Implements IEPMADirectoryAccess.GetFileContent
    If searchOption = Nothing Then
        searchOption = SearchOption.TopDirectoryOnly
    End If

    LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
    Using WindowsIdentity.Impersonate(UserToken)
        Return Directory.GetFiles(filePath, searchPattern, searchOption)
    End Using
End Function
''' <summary>
''' Get the name of the Ward from the directory of the current file path 
''' </summary>
Public Function GetWardName(filePath As String) As String Implements IEPMADirectoryAccess.GetWardName
    LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
    Using WindowsIdentity.Impersonate(UserToken)
        Return New DirectoryInfo(Path.GetDirectoryName(filePath)).Name
    End Using
End Function
''' <summary>
''' Creates a directory for the given path 
''' </summary>
Public Sub CreateDirectory(directoryPath As String) Implements IEPMADirectoryAccess.CreateDirectory
    LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
    Using WindowsIdentity.Impersonate(UserToken)
        Directory.CreateDirectory(directoryPath)
    End Using
End Sub
''' <summary>
''' Deletes a file from the specified path
''' </summary>
Public Sub DeleteFile(filePath As String) Implements IEPMADirectoryAccess.DeleteFile
    LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
    Using WindowsIdentity.Impersonate(UserToken)
        File.Delete(filePath)
    End Using
End Sub
''' <summary>
''' Copies a file from the source path to the destination path 
''' </summary>
Public Sub CopyFile(sourceFilePath As String, destFilePath As String, overwrite As Boolean) Implements IEPMADirectoryAccess.CopyFile
    LogonUser(UserName, Domain, Password, LogonType.LOGON32_LOGON_NEW_CREDENTIALS, 0, UserToken)
    Using WindowsIdentity.Impersonate(UserToken)
        File.Copy(sourceFilePath, destFilePath, overwrite)
    End Using
End Sub

part of the code in the parallel loop looks like this:

                                                        'If PC is switched on 
                                                         If IsOnline(device.PCName) Then

                                                             'For each PC of the ward, get the corresponding folder path
                                                             targetPath = "\\" + device.PCName + "\c$Report P\"

                                                             'Requires access to the network share 
                                                             If Not Directory.Exists(targetPath) Then
                                                                 DirectoryAccess.CreateDirectory(targetPath)
                                                             End If

                                                             'Requires access to the network share 
                                                             For Each fileName As String In DirectoryAccess.GetFileContent(targetPath, "*.pdf")
                                                                 'Purge (Delete) previous versions of this file in the destination folder  
                                                                 Dim fileConst As String

                                                                 fileConst = arr(1)
                                                                 If fileName.Contains(fileConst) Then
                                                                     'Requires access to the network share 
                                                                     DirectoryAccess.DeleteFile(fileName)
                                                                 End If
                                                             Next

                                                             DirectoryAccess.CopyFile(f, Path.Combine(targetPath, Path.GetFileName(f), True)


                                                         End If

In the main module I am timing the difference in copying the files when using a normal for loop compared to a parallel for loop but with the same code content within the for loops:

enter image description here

Initially, the parallel copying is 18 seconds but then becomes 2.82 seconds for the second run.

enter image description here

The third run is 1.81 seconds.

I have checked that the using blocks for impersonation have correctly disposed and reverted to my original credentials after exiting the using block. I am not sure why it is slow in the first run but then speeds up? Could it be that initially the four PCs are inactive, so the process of copying activates them but takes longer?

I have an IsOnline function that checks if the PCs are powered on, if not I just skip them to ensure it doesn't slow down the process.

enter image description here


Solution

  • Turns out it was slow because time was measured on different number of pcs on at any one time. Some PCs went to sleep during the measurement so affected the processing time