How to improve performance?
throwaway4rust opened this issue · comments
import winim/lean
import strformat except `&`
proc main =
var sc = OpenSCManager(nil, nil, SC_MANAGER_ENUMERATE_SERVICE)
if sc != 0:
defer: CloseServiceHandle(sc)
const
srvType = SERVICE_WIN32
srvState = SERVICE_STATE_ALL
var bytesNeeded, srvCount, resumeHandle: DWORD
# Use nil pointer in first call to avoid realloc the buffer later
EnumServicesStatus(sc, srvType, srvState, nil, 0, &bytesNeeded, &srvCount,
&resumeHandle)
# Use string for the buffer, or you can use alloc() and then dealloc() later.
var buffer = newString(bytesNeeded)
# Cast the pointer to what EnumServicesStatus want.
# Here &buffer = addr buffer[0]
let lpService = cast[LPENUM_SERVICE_STATUS](&buffer)
# We can access the low level c array easily by using Nim's UncheckedArray.
let services = cast[ptr UncheckedArray[ENUM_SERVICE_STATUS]](lpService)
EnumServicesStatus(sc, srvType, srvState, lpService, bytesNeeded,
&bytesNeeded, &srvCount, &resumeHandle)
echo fmt"Count of NT Services using EnumServicesStatus: {srvCount}"
for i in 0..<srvCount:
echo fmt"{services[i].lpServiceName}: {services[i].lpDisplayName}"
when isMainModule:
main()
The following code when compiled with nim c -d:danger -d:release --gc:arc
and tested with
Measure-Command { main.exe }
Takes 18ms on my machine.
Measure-Command { get-service }
Takes 3ms.
Is there any reason why or does anyone know how to improve performance?
For other program, you may try adding --opt:speed
and --passc:-flto
. For this program, I don't think it can be improved anymore. Because I get the same result (about 20ms) if I comment out all the lines (compile an empty file).
Maybe powershell get-service
is using some pre-allocation strategy to do only 1 call?
It seems odd that powershell commandlet can beat low level code like this and also by providing more output than the Nim code above.
BTW if you feel like this is not worth discussing if we simply do not know and cant find out feel free to close the issue 👍
Thanks a lot for winim it's really an amazing library!
measure-command { get-service | out-default }
Is the correct way to measure this commandlet as by default it's not measuring printing out on stdout.