Em rotinas de processamentos é comum a utilização de refresh de componente ou alteração de algum dado de interface para melhorar o feedback do processamento ao usuário.
O uso intenso de interação com componentes de tela durante um processamento é prejudicial ao desempenho do Microsiga Protheus, pois cada interação executa uma troca de mensagem entre o servidor e o cliente. Quando extrapolado em uma situação de concorrência intensa no servidor, a interação pode prejudicar drasticamente o desempenho. Verifique o seguinte teste:
// UIUpdatePerformanceTest.prw
#INCLUDE "TOTVS.CH"
#DEFINE INTERACTIONS 100000
Function UIUpdatePerformanceTest()
Local oDlg := Nil
Local oSay := Nil
Local oMeter := Nil
Local nMeter := 0
Define Dialog oDlg Title "UI Update Performance Test" From 0,0 To 75,400 Pixel
@05,05 Say oSay Prompt "Texto" Of oDlg Pixel Colors CLR_RED,CLR_WHITE Size 185,20
@15,05 Meter oMeter Var nMeter Pixel Size 185,20 Of oDlg
Activate Dialog oDlg Centered On Init (IntenseUpdate(oDlg, oSay, oMeter),ControlledUpdate(oDlg, oSay, oMeter))
Return
Static Function IntenseUpdate(oDlg, oSay, oMeter)
Local nSeconds := 0
Local nCount := 0
oMeter:SetTotal(INTERACTIONS)
nSeconds := Seconds()
oSay:SetText("Interagindo intensamente")
For nCount := 1 To INTERACTIONS
oMeter:Set(nCount)
oDlg:CommitControls()
Next
ConOut("Para " + AllTrim(Str(INTERACTIONS)) + " interações, utilizou-se um tempo de " + AllTrim(Str(Seconds()-nSeconds)) + " segundos.")
Return
Static Function ControlledUpdate(oDlg, oSay, oMeter)
Local nSeconds := 0
Local nCount := 0
Local nLastUpdate := 0
oMeter:SetTotal(INTERACTIONS)
nSeconds := Seconds()
oSay:SetText("Interagindo controladamente")
For nCount := 1 To INTERACTIONS
If (Seconds() - nLastUpdate) > 1 // Se passou 1 segundo desde a última atualização da tela
oMeter:Set(nCount)
oDlg:CommitControls() // Para atualizar a tela e o usuário receber o feedback
nLastUpdate := Seconds()
EndIf
Next
// Efetua uma atualização final para garantir que o usuário veja o resultado do processamento
oMeter:Set(nCount)
oDlg:CommitControls() // Para atualizar a tela e o usuário receber o feedback
ConOut("Para " + AllTrim(Str(INTERACTIONS)) + " interações controladas, utilizou-se um tempo de " + AllTrim(Str(Seconds()-nSeconds)) + " segundos.")
Return
O resultado apresentado foi:
Para 100000 interações, utilizou-se um tempo de 0.938 segundos.
Para 100000 interações controladas, utilizou-se um tempo de 0.055 segundos.
Nas interações não controladas foram enviados 100000 comandos de atualização de tela, já na função de interação controlada o número enviado foi dramaticamente menor, pois a atualização só ocorria uma vez por segundo.
Essa situação pode ser aplicada em toda e qualquer interação de atualização ou modificação de componente de tela.