Jump to content
mutleey

Aliviar uso da CPU

Recommended Posts

Pessoal existe alguma maneira de aliviar o uso da CPU usando qualquer parâmetro abaixo de 10 milissegundos?

Eu gostaria de usar um sleep(5)  ou sleep(3) por exemplo, mas sei que sleep() não é possível porque o uso de 1 a 9 será automaticamente padronizado para 10 milissegundos.

Alguem sugere alguma alternativa?

O que acontece é que estou fazendo uma automação que requer uma precisão porque usa como entrada um receptor infravermelho, a leitura é muito rápida e se eu usar um "loop" de verificação com um tempo de 10 ms que é o mínimo do sleep() as vezes (raro) a rotina perde a leitura de entrada, vou dar um exemplo  ..

 

While True
    ; verificação de entrada... perfeito 0% de erro, mas o uso da CPU atinge 50%
WEnd

While True
    ; verificação de entrada... 0% de uso da CPU, mas 10% de chance de dar erro
    Sleep(10)
WEnd

Obs: tentei  UDF _HighPrecisionSleep() porem o tempo "pelo menos aqui" continua entre 10 e 15 ms.

 

Qualquer dica será de grande ajuda..

Share this post


Link to post
Share on other sites

Use "Select ou Switch" Independente de onde o loop estiver, eles serão chamados na próxima volta caso algo neles seja executado durante o loop, dessa forma você pode colocar até um sleep de sei lá 10 segundos no loop, se vc executar alguma função contida nele e o loop já estiver passado pelo Switch ou select ele será executada na próxima volta independente de onde o loop estiver.

"a rotina perde a leitura de entrada" Nunca será perdida

while true

Select
      case _Ispressed("Tecla Exemplo1")
        _FunçãoQualquer1()
      case _Ispressed("Tecla Exemplo2")
        _FunçãoQualquer2()
EndSelect

sleep(10000) <---Se o loop estiver parado aqui esperando os 10 segundos e você apertar uma das teclas de exemplo, na proxima volta a função da tecla será executada. Dessa forma vc não vai precisar esperar que o loop passe por um "if" e a precisão será 100%.
wend

 

Edited by Pedro Pinheiro

Share this post


Link to post
Share on other sites

Pedro sua sujestão é bacana mas como citei no primeiro post a rotinha não espera por "keys" ou "switchs" desta forma ficaria facil pois ao apertar uma tecla toda a estrutura da função seria chamada e assim não haveria erro, o que acontece é que dentro da rotina tem uma verificação de sensores ópticos, e estes sensores são mega rápidos na leitura, então estes 10 ms de "pausa" no looping que seria para aliviar o uso da cpu... (raro) mais tem chance de erro, acredito que a "leitura" destes sensores é muito menor que 10 ms, se eu uso a rotina sem a "pausa", sleep() ou GUIGetMsg() a precisão fica 101% o unico problema é que o uso da cpu vai a 50% e com uma pausa de 10 ms na rotina o uso da cpu é 0%.

Edited by mutleey

Share this post


Link to post
Share on other sites

@Pedro Pinheiro quando o loop está parado no sleep ele não executa nenhuma outra função então se está esperando o sleep de 10 milisegundos terminar e apertar alguma tecla vai falhar sim pois não esta passando pelo "Select ou Switch" naquele momento!

#include <Misc.au3>

Local $hDLL = DllOpen("user32.dll")

$contar = 0
While 1
    Select
        Case _IsPressed("41", $hDLL)
            $contar += 1
            ExitLoop
    EndSelect
    Sleep(10000); <---Se o loop estiver parado aqui não vai executar o Select
WEnd

MsgBox(4096, '', $contar)

 

Share this post


Link to post
Share on other sites

Depois de muita procura e testes, achei uma modificação da UDF _HighPrecisionSleep() que retornou resultados satisfatorios..

Pra quem estiver com o mesmo problema segue o código.

; mutleey

HotKeySet("{ESC}", "__Exit")


Global $ntdll = DllOpen("ntdll.dll")
Global $winmm = DllOpen("winmm.dll")


While True
    $timer = TimerInit()
    MsSleep(1)
    ConsoleWrite('> ' & TimerDiff($timer) & @LF)
WEnd

Func MsSleep($MS)
    $MS *= 1000
    DllCall("winmm.dll", "int", "timeBeginPeriod", "int", "1")
    DllCall("ntdll.dll", "dword", "NtDelayExecution", "int", 0, "int64*", -10 * $MS)
EndFunc   ;==>MsSleep


Func __Exit()
    DllClose("ntdll.dll")
    DllClose("winmm.dll")
    Exit
EndFunc

 

  • Like 2

Share this post


Link to post
Share on other sites

@mutleey vou guardar aqui e com certeza será de grande utilidade principalmente para funções de crédito!

  • Thanks 1

Share this post


Link to post
Share on other sites

@mutleey

Que tal desvincular a função de dentro do loop?
Eu não tenho ideia de como o AutoIt resolve internamente o uso do AdlibRegister, mas amontar todas as funções dentro do loop pode ter um momento que as coisas podem sair do controle... Algumas demora mais do que o esperado, e essa demora causa um efeito cascata, será que não?

Então, a proposta do AdlibRegister é justamente essa, desafogar o loop.

Veja este exemplo.

;~ #AutoIt3Wrapper_AU3Check_Parameters= -q -d -w 1 -w 2 -w 3 -w- 4 -w 5 -w 6 -w- 7
;~ #Tidy_Parameters=/sf

#include-once
#include <SliderConstants.au3>
#include <Array.au3>
#include <GUIConstantsEx.au3>

OnAutoItExitRegister("OnExit")

Opt("GUIOnEventMode", 1)
Opt("GUIEventOptions", 1)
Opt("MustDeclareVars", 1)

Global $aGuiSize[2] = [800, 600]
Global $sGuiTitle = "GuiTitle"
Global $hGui

Global $aSlider[4], $aVal[4] = [100, 100, 100, 100], $aMov[4] = [-1, -1, -1, -1]

$hGui = GUICreate($sGuiTitle, $aGuiSize[0], $aGuiSize[1])
GUISetOnEvent($GUI_EVENT_CLOSE, "Quit")

$aSlider[0] = GUICtrlCreateSlider(10, 10, 20, 200, $TBS_VERT + $TBS_AUTOTICKS)
GUICtrlSetData($aSlider[0], $aVal[0])
AdlibRegister("Slider0", 100) ; executa a função Slider0 a cada 100 mili segundos


$aSlider[1] = GUICtrlCreateSlider(50, 10, 20, 200, $TBS_VERT + $TBS_AUTOTICKS)
GUICtrlSetData($aSlider[1], $aVal[1])
AdlibRegister("Slider1", 200) ; executa a função Slider1 a cada 200 mili segundos

$aSlider[2] = GUICtrlCreateSlider(90, 10, 20, 200, $TBS_VERT + $TBS_AUTOTICKS)
GUICtrlSetData($aSlider[2], $aVal[2])
AdlibRegister("Slider2", 300) ; executa a função Slider2 a cada 300 mili segundos

$aSlider[3] = GUICtrlCreateSlider(140, 10, 20, 200, $TBS_VERT + $TBS_AUTOTICKS)
GUICtrlSetData($aSlider[3], $aVal[3])
AdlibRegister("Slider3", 400) ; executa a função Slider3 a cada 400 mili segundos

GUISetState(@SW_SHOW, $hGui)

While Sleep(25)
WEnd

Func OnExit()
    ; antes de encerrar o script, eu cancelo todos os adlib, é uma boa prática
    ; pois como o adlib não respeita um loop, o Exit pode ainda não ter sido concluído
    ; e o AutoIt pode executar alguma função do adlib
    
    AdlibUnRegister("Slider0")
    AdlibUnRegister("Slider1")
    AdlibUnRegister("Slider2")
    AdlibUnRegister("Slider3")
    GUISetState($hGui, @SW_HIDE)
    GUIDelete($hGui)
EndFunc   ;==>OnExit

Func Quit()
    Exit
EndFunc   ;==>Quit

Func Slider0()
    $aVal[0] = GUICtrlRead($aSlider[0]) + $aMov[0]
    If $aVal[0] <= 0 Or $aVal[0] >= 100 Then $aMov[0] *= -1
    GUICtrlSetData($aSlider[0], $aVal[0])
EndFunc   ;==>Slider0

Func Slider1()
    $aVal[1] = GUICtrlRead($aSlider[1]) + $aMov[1]
    If $aVal[1] <= 0 Or $aVal[1] >= 100 Then $aMov[1] *= -1
    GUICtrlSetData($aSlider[1], $aVal[1])
EndFunc   ;==>Slider1

Func Slider2()
    $aVal[2] = GUICtrlRead($aSlider[2]) + $aMov[2]
    If $aVal[2] <= 0 Or $aVal[2] >= 100 Then $aMov[2] *= -1
    GUICtrlSetData($aSlider[2], $aVal[2])
EndFunc   ;==>Slider2

Func Slider3()
    $aVal[3] = GUICtrlRead($aSlider[3]) + $aMov[3]
    If $aVal[3] <= 0 Or $aVal[3] >= 100 Then $aMov[3] *= -1
    GUICtrlSetData($aSlider[3], $aVal[3])
EndFunc   ;==>Slider3

 

  • Thanks 1

Share this post


Link to post
Share on other sites
2 hours ago, Luigi said:

@mutleey

Que tal desvincular a função de dentro do loop?

@Luigi Mais o motivo principal do tópico é realmente aliviar o "loop", acho que você entendeu errado, por padrão seja com Sleep(),  AdlibRegister() o AutoIT vai trabalhar com no minimo 10ms.. e como disse no inicio do tópico estes 10ms para o meu proposito era muito (ainda mais que o autoit não tem um "time" muito correto) então mesmo eu colocando  10ms de "pausa" muitas vezes estes 10 se torna, 15, 20ms ou mais, este foi o real motivo de chamar a função dentro do looping, ou seja aliviar o uso de cpu.

Edited by mutleey

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


×