Skip to content

Instantly share code, notes, and snippets.

@timleavitt
Last active September 12, 2018 20:50
Show Gist options
  • Star 4 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save timleavitt/bab7b7af5021fb2b5713be79db86717c to your computer and use it in GitHub Desktop.
Save timleavitt/bab7b7af5021fb2b5713be79db86717c to your computer and use it in GitHub Desktop.
Caché ObjectScript demo - various loops to iterate over pieces of a delimited string
/// This class demonstrates the performance of various loops that iterate over the pieces of a delimited string.
Class DC.LoopPerformance
{
ClassMethod Run(pIterations As %Integer = 10000, pPieceLength As %Integer = 20, pNumberPieces = 100, pDelimiter = ",")
{
#define START(%msg) Write %msg Set start = $zh
#define END Write ($zh - start)," seconds",!
// Build a random string given the specifications
Set tString = ""
For i=1:1:pNumberPieces {
Set tPiece = $System.Encryption.GenCryptRand(pPieceLength) //Random string of a specified length.
Set tString = tString_$Case(i,1:"",:",")_tPiece
Set tStringArray($i(tStringArray)) = tPiece
}
Write "Iterating "_pIterations_" times over all the pieces of a string with "_pNumberPieces_" "_","_"-delimited pieces of length "_pPieceLength_":",!
// Iterate over the pieces of the string pIterations times using $Length/$Piece
$$$START("Using $Length/$Piece (hardcoded delimiter): ")
For i=1:1:pIterations {
Set tLength = $Length(tString,",")
For j=1:1:tLength {
Set tValue = $Piece(tString,",",j)
}
}
$$$END
// Iterate over the pieces of the string pIterations times using $Length/$Piece
$$$START("Using $Length/$Piece: ")
For i=1:1:pIterations {
Set tLength = $Length(tString,pDelimiter)
For j=1:1:tLength {
Set tValue = $Piece(tString,pDelimiter,j)
}
}
$$$END
// Iterate over the pieces of the string pIterations times using $Find/$Extract
$$$START("Using $Find/$Extract (hardcoded delimiter): ")
For i=1:1:pIterations {
Set tPosition = 0
Do {
Set tNewPosition = $Find(tString,",",tPosition)
Set tValue = $Select(tNewPosition'=0:$Extract(tString,tPosition,tNewPosition-2),1:$Extract(tString,tPosition,*))
Set tPosition = tNewPosition
} While tPosition '= 0
}
$$$END
// Iterate over the pieces of the string pIterations times using $Find/$Extract
$$$START("Using $Find/$Extract: ")
For i=1:1:pIterations {
Set tPosition = 0
Do {
Set tNewPosition = $Find(tString,pDelimiter,tPosition)
Set tValue = $Select(tNewPosition'=0:$Extract(tString,tPosition,tNewPosition-2),1:$Extract(tString,tPosition,*))
Set tPosition = tNewPosition
} While tPosition '= 0
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListLength, retrieving items with $List
$$$START("Using $ListFromString/$ListLength/$List (hardcoded delimiter): ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,",")
Set tLen = $ListLength(tList)
For j=1:1:tLen {
Set tValue = $List(tList,j)
}
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListLength, retrieving items with $List
$$$START("Using $ListFromString/$ListLength/$List: ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,pDelimiter)
Set tLen = $ListLength(tList)
For j=1:1:tLen {
Set tValue = $List(tList,j)
}
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListNext
$$$START("Using $ListFromString/$ListNext (hardcoded delimiter): ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,",")
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListNext
$$$START("Using $ListFromString/$ListNext: ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,pDelimiter)
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
$$$END
Write "****************************************************",!
// Convert the string to a $ListBuild list, then iterate using $ListNext
Set tList = $ListFromString(tString,",")
$$$START("Using $ListFromString/$ListNext (not including conversion to $ListBuild list): ")
For i=1:1:pIterations {
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
$$$END
// Process an array
$$$START("Using one-argument $Order over an equivalent local array with integer subscripts: ")
For i=1:1:pIterations {
Set tKey = ""
For {
Set tKey = $Order(tStringArray(tKey))
Quit:tKey=""
Set tValue = tStringArray(tKey)
}
}
$$$END
// Process an array
$$$START("Using three-argument $Order over an equivalent local array with integer subscripts: ")
For i=1:1:pIterations {
Set tKey = ""
For {
Set tKey = $Order(tStringArray(tKey),1,tValue)
Quit:tKey=""
}
}
$$$END
}
/// Runs only the O(n) implementations
ClassMethod RunLinearOnly(pIterations As %Integer = 100000, pPieceLength As %Integer = 20, pNumberPieces = 100, pDelimiter = ",")
{
#define START(%msg) Write %msg Set start = $zh
#define END Write ($zh - start)," seconds",!
// Build a random string given the specifications
Set tString = ""
For i=1:1:pNumberPieces {
Set tPiece = $System.Encryption.GenCryptRand(pPieceLength) //Random string of a specified length.
Set tString = tString_$Case(i,1:"",:",")_tPiece
Set tStringArray($i(tStringArray)) = tPiece
}
// Oddly, there seems to be some bias against the first thing that's run. Run $ListFromString/ListNext once to start.
For i=1:1:pIterations {
Set tList = $ListFromString(tString,",")
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
Write "Iterating "_pIterations_" times over all the pieces of a string with "_pNumberPieces_" "_","_"-delimited pieces of length "_pPieceLength_":",!
// Convert the string to a $ListBuild list, then iterate using $ListNext
$$$START("Using $ListFromString/$ListNext (While): ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,",")
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListNext (in a For loop instead)
$$$START("Using $ListFromString/$ListNext (For/Quit): ")
For i=1:1:pIterations {
Set tList = $ListFromString(tString,",")
Set tPtr = 0
For {
Quit:'$ListNext(tList,tPtr,tValue)
}
}
$$$END
// Convert the string to a $ListBuild list, then iterate using $ListNext
Set tList = $ListFromString(tString,",")
$$$START("Using $ListFromString/$ListNext (While, not including conversion to $ListBuild list): ")
For i=1:1:pIterations {
Set tPtr = 0
While $ListNext(tList,tPtr,tValue) {}
}
$$$END
// Iterate over the pieces of the string pIterations times using $Find/$Extract
$$$START("Using $Find/$Extract (Do...While): ")
For i=1:1:pIterations {
Set tPosition = 0
Do {
Set tNewPosition = $Find(tString,",",tPosition)
Set tValue = $Select(tNewPosition:$Extract(tString,tPosition,tNewPosition-2),1:$Extract(tString,tPosition,*))
Set tPosition = tNewPosition
} While tPosition '= 0
}
$$$END
// Iterate over the pieces of the string pIterations times using $Find/$Extract
$$$START("Using $Find/$Extract (For/Quit): ")
For i=1:1:pIterations {
Set tPosition = 0
For {
Set tNewPosition = $Find(tString,",",tPosition)
Set tValue = $Select(tNewPosition:$Extract(tString,tPosition,tNewPosition-2),1:$Extract(tString,tPosition,*))
Quit:tNewPosition=0
Set tPosition = tNewPosition
}
}
$$$END
// Process an array
$$$START("Using one-argument $Order (For): ")
For i=1:1:pIterations {
Set tKey = ""
For {
Set tKey = $Order(tStringArray(tKey))
Quit:tKey=""
Set tValue = tStringArray(tKey)
;Do things with tValue here.
}
}
$$$END
// Process an array
$$$START("Using one-argument $Order (While): ")
For i=1:1:pIterations {
Set tKey = $Order(tStringArray(""),1,tValue)
While tKey {
Set tValue = tStringArray(tKey)
;Do things with tValue here.
Set tKey = $Order(tStringArray(tKey))
}
}
$$$END
// Process an array
$$$START("Using three-argument $Order (For): ")
For i=1:1:pIterations {
Set tKey = ""
For {
Set tKey = $Order(tStringArray(tKey),1,tValue)
Quit:tKey=""
;Do things with tValue here.
}
}
$$$END
// Process an array
$$$START("Using three-argument $Order (While): ")
For i=1:1:pIterations {
Set tKey = $Order(tStringArray(""),1,tValue)
While tKey {
;Do things with tValue here.
Set tKey = $Order(tStringArray(tKey),1,tValue)
}
}
$$$END
}
}
@evshvarov
Copy link

See the related discussion on InterSystems Developer Community.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment