views:

1288

answers:

4

The following is the usual log function I utilize in alot of my vbscripts which I modify accordingly. I feel it writes too slow. I got 3 questions:

  1. Any ideaas on how to optimize this so it writes faster?
  2. Would it be faster to store all text in a string first then run the function OutputToLog or would it be faster to execute OutputToLog each time I needed to insert a string into the text file?
  3. If drive space wasn't a factor, is it possible to run out of memory while writing to a text file during execution...causing the script to execute slower and slower?

Here is my vbscript function

Function OutputToLog (strToAdd)  
    Dim strDirectory,strFile,strText, objFile,objFolder,objTextFile,objFSO
    strDirectory = "c:\log"
    strFile = "\log-"& StampNow &  ".bat"
    'strText = "test"
    strText = strToAdd

    ' Create the File System Object
    Set objFSO = CreateObject("Scripting.FileSystemObject")

    ' Check that the strDirectory folder exists
    If objFSO.FolderExists(strDirectory) Then
       Set objFolder = objFSO.GetFolder(strDirectory)
    Else
       Set objFolder = objFSO.CreateFolder(strDirectory)
       'WScript.Echo "Just created " & strDirectory
    End If

    If objFSO.FileExists(strDirectory & strFile) Then
       Set objFolder = objFSO.GetFolder(strDirectory)
    Else
       Set objFile = objFSO.CreateTextFile(strDirectory & strFile)
       'Wscript.Echo "Just created " & strDirectory & strFile
    End If

    set objFile = nothing
    set objFolder = nothing
    ' OpenTextFile Method needs a Const value
    ' ForAppending = 8 ForReading = 1, ForWriting = 2
    Const ForAppending = 8

    Set objTextFile = objFSO.OpenTextFile _
    (strDirectory & strFile, ForAppending, True)

    ' Writes strText every time you run this VBScript
    objTextFile.WriteLine(strText)
    objTextFile.Close
End Function

thanks in advance

A: 

If you're doing a lot of small writes then refactoring the checks for FolderExists and FileExists out will help a bit. Maybe try to write to the file, trapping any errors, and check for FolderExists and FileExists in the error handler and create them if necessary?

It'll be quicker to output one large string rather than several small ones, but you have to balance that against the possibility of losing log entries if your program crashes.

Memory shouldn't be a problem unless you're writing a humungous string to the file, and probably not even then.

Because you're appending to the file, the longer the log file gets the longer the write will take, because (AFAIK) the entire file has to be rewritten each time. That's another reason for writing longer strings less frequently.

Could you use Windows' Event Log instead?

gkrogers
would it be faster to create smaller files and then combine them all at the end of the process?
phill
I can't use the event log because I'm using the log file to construct a batch file to run afterwards. In one instance I found it is easier to create and then execute a batch file of xcopy commands than it is to use the copyfile object in vbscript.
phill
I just modified a script to store everything in a string before executing the above function. It seems to be moving along faster for the now. I guess we will really see what happens in the next 2 hours or so. It has to sift through 50 gigs of files and folders before outputing to a file.
phill
Writing itself is not the most cost effective operation opening / scanning (even eof) / closing the file is what usually slows down file access.
Martijn Laarman
A: 

Do all your folder/file checking and creating once in a prep function, then you can just append to the log file safe in the knowledge that it'll be there? Also, you should be able to just create the fso object once.

Something like the following (untested code)

Dim loggerFSO

Function PrepLog
    dim objFolder
    ' Create the File System Object
    if loggerFSO is nothing then Set loggerFSO = CreateObject("Scripting.FileSystemObject")

    ' Check that the strDirectory folder exists
    If loggerFSO.FolderExists(strDirectory) Then
       Set objFolder = loggerFSO.GetFolder(strDirectory)
    Else
       Set objFolder = loggerFSO.CreateFolder(strDirectory)
       'WScript.Echo "Just created " & strDirectory
    End If

    If loggerFSO.FileExists(strDirectory & strFile) Then
       ' do nothing
    Else
       loggerFSO.CreateTextFile(strDirectory & strFile)
       'Wscript.Echo "Just created " & strDirectory & strFile
    End If
End function

Function OutputToLog (strToAdd)  
    Dim strDirectory,strFile,strText, objTextFile
    strDirectory = "c:\log"
    strFile = "\log-"& StampNow &  ".bat"
    'strText = "test"
    strText = strToAdd

    ' Create the File System Object
    if loggerFSO is nothing then Set loggerFSO = CreateObject("Scripting.FileSystemObject")

    ' OpenTextFile Method needs a Const value
    ' ForAppending = 8 ForReading = 1, ForWriting = 2
    Const ForAppending = 8

    Set objTextFile = loggerFSO.OpenTextFile _
    (strDirectory & strFile, ForAppending, True)

    ' Writes strText every time you run this VBScript
    objTextFile.WriteLine(strText)
    objTextFile.Close
End Function
Binary Worrier
+1  A: 

I think you'd want to both create your FSO objects and open your log file outside the the OutputToLog function. It may not save much time, but why create objects, open and close files with every write?

Otherwise if you want to keep the functions as is, doing just one write should be quicker.

Scott Hoffman
+1 Opening / scanning / closing are the most cost effective operations for windows so your spot on. Also the code looks like it could use the exclusive access by keeping the in use.
Martijn Laarman
A: 

Don't close the file between calls, let the textstream-object take care of closing when it terminates.

Dim OutputToLogFileObject
Function OutputToLog (strToAdd)  
    Dim strDirectory,strFile,strText, objFile,objFolder,objTextFile,objFSO
    If IsEmpty(OutputToLogFileObject) Then
        strDirectory = "c:\log"
        strFile = "\log-"& StampNow &  ".bat"
        'strText = "test"
        strText = strToAdd

        ' Create the File System Object
        Set objFSO = CreateObject("Scripting.FileSystemObject")

        ' Check that the strDirectory folder exists
        If objFSO.FolderExists(strDirectory) Then
           Set objFolder = objFSO.GetFolder(strDirectory)
        Else
           Set objFolder = objFSO.CreateFolder(strDirectory)
           'WScript.Echo "Just created " & strDirectory
        End If

        If objFSO.FileExists(strDirectory & strFile) Then
           Set objFolder = objFSO.GetFolder(strDirectory)
        Else
           Set objFile = objFSO.CreateTextFile(strDirectory & strFile)
           'Wscript.Echo "Just created " & strDirectory & strFile
        End If

        set objFile = nothing
        set objFolder = nothing
        ' OpenTextFile Method needs a Const value
        ' ForAppending = 8 ForReading = 1, ForWriting = 2
        Const ForAppending = 8

        Set OutputToLogFileObject = objFSO.OpenTextFile _
        (strDirectory & strFile, ForAppending, True)
    End If
    OutputToLogFileObject.WriteLine strText
 End Function
svinto