Olaf Doschke
Programmer
In a curent project we change record IDs from integer to GUID. It's rather easy to create GUIDs with calls to Windows API. The main call is CoCreateGuid, which creates a binary string that you can transform with StringFromGUID2.
Many functions I found include the declaration within the function, eg:
This makes sure CoCreateGUID is declared, before it is used. It does not matter how often the Declare is made, it does not error, if you define it twice, it's just important, that it is made at least once, otherwise the call to CoCreateGuid(@lcGuid) will error.
Most people tend to program in this way to prevent errors, as security goes first. That's perfectly okay, but let's see the huge performance difference:
Running this on my laptop the loop takes about 25 seconds.
If I make the Declaration once at the first line (which is commented) and comment out the Declaration within the function, the loop takes about 0.55 to 0.6 seconds.
The disadvantage is of course, the function itself does not make sure the needed declaration is done. Think of the bigger picture: you may put the declaration in the main prg of your application, and it will work anyway. But if you use that as a default value of guid fields, the database only works with applications that make that declare within their code before adding data to that database.
There is a way to optimize this and have both the security of declaring the needed API call and make that declaration only when needed:
It still only takes about 0.6 to 0.7 seconds, slightly slower than the fastest version, but still much faster than the usual "safer" version, although this is exactly that safe. Therefore the thread caption: Errors welcome. Don't be afraid to code in such ways, as it allows you to set the requirements or prerequisites only, if that is really needed.
You may say it's not relevant, because GUID creation is fast enough if you think of users manually adding data, but think of mass data, eg data migration, that can make a huge difference.
Bye, Olaf.
Many functions I found include the declaration within the function, eg:
Code:
Function CreateGuid()
Declare Integer CoCreateGuid In Ole32.Dll String @cGuid
Local lcGuid
lcGuid = Space(16)
=CoCreateGuid(@lcGuid)
Return m.lcGuid
EndFunc
This makes sure CoCreateGUID is declared, before it is used. It does not matter how often the Declare is made, it does not error, if you define it twice, it's just important, that it is made at least once, otherwise the call to CoCreateGuid(@lcGuid) will error.
Most people tend to program in this way to prevent errors, as security goes first. That's perfectly okay, but let's see the huge performance difference:
Code:
* Declare Integer CoCreateGuid In Ole32.Dll String @cGuid
Local lnCount, lnTime
lnTime = Seconds()
For lnCount = 1 to 100000
CreateGUID()
EndFor
? Seconds()-lnTime
Function CreateGuid()
Declare Integer CoCreateGuid In Ole32.Dll String @cGuid
Local lcGuid
lcGuid = Space(16)
=CoCreateGuid(@lcGuid)
Return m.lcGuid
EndFunc
Running this on my laptop the loop takes about 25 seconds.
If I make the Declaration once at the first line (which is commented) and comment out the Declaration within the function, the loop takes about 0.55 to 0.6 seconds.
The disadvantage is of course, the function itself does not make sure the needed declaration is done. Think of the bigger picture: you may put the declaration in the main prg of your application, and it will work anyway. But if you use that as a default value of guid fields, the database only works with applications that make that declare within their code before adding data to that database.
There is a way to optimize this and have both the security of declaring the needed API call and make that declaration only when needed:
Code:
Local lnCount, lnTime
lnTime = Seconds()
For lnCount = 1 to 100000
CreateGUID()
EndFor
? Seconds()-lnTime
Function CreateGuid()
Try
Local lcGuid
lcGuid = " " && Space(16)
=CoCreateGuid(@lcGuid)
Catch
Declare Integer CoCreateGuid In Ole32.Dll String @cGuid
Endtry
Return Iif(Empty(lcGuid),CreateGuid(),lcGuid)
EndFunc
It still only takes about 0.6 to 0.7 seconds, slightly slower than the fastest version, but still much faster than the usual "safer" version, although this is exactly that safe. Therefore the thread caption: Errors welcome. Don't be afraid to code in such ways, as it allows you to set the requirements or prerequisites only, if that is really needed.
You may say it's not relevant, because GUID creation is fast enough if you think of users manually adding data, but think of mass data, eg data migration, that can make a huge difference.
Bye, Olaf.