BlackTDN :: Performance : Função Padrão vs Função de Usuário
Sabemos que Performance não é um forte dos produtos TOTVS, não que a tecnologia não permita isso, mas, principalmente, porque os desenvolvedores não se preocupam muito com ela. Performance, me parece, é algo relevado a segundo, terceiro ou mesmo a nenhum plano. Utilizam do seguinte jargão: “No que está funcionando não se mexe”.
E isso nos é custoso. Custa em tempo de CPU, custa em paciência e custa, principalmente, o nosso precioso tempo. Não basta ter um servidor “parrudo” (que normalmente é a desculpa que se dá) o sistema tem que ser funcional e, de certa forma, rápido.
Para exemplificar vou usar de duas funções, escritas em ADVPL, documentadas no TDN e de livre acesso aos usuários. SomaStr(cValor1,cValor2) : cSoma e MultStr(cValor1,cValor2) : cMult. Para confrontá-las utilizarei dos métodos Add() e Mult() da Classe tBigNumber.
No primeiro caso, SomaStr() fez páreo com o método Add() de tBigNumber apresentando diferenças insignificantes que não comprometeriam a performance do sistema no que diz respeito a utilizá-la em detrimento à função de usuário.
Já no segundo caso, MultStr() é muito custosa. Utiliza um tempo considerável de CPU e sua performance degrada exponencialmente a cada iteração. Neste caso é preferível utilizar a função de usuário ao invés da função padrão.
Utilizei, para o exemplo, SomaStr() e MultStr() mas poderia utilizar qualquer outra função ou programa (principalmente de relatório).
Aos Dados:
Para SomaStr()
| tBigNumber:ADD x SomaStr | "12345678901234567…12345678901234567890" + "12345678901234567…12345678901234567890" |
| Iterações | 10.000 |
| tBigN Elapsed | 00:00:17 |
| Value | 246913578024691357…7802469135780 |
| SomaStr Elapsed | 00:00:19 |
| Value | 246913578024691357…7802469135780 |
| Diff tBigN x SomaStr | 00:00:02 |
Neste primeiro exemplo executamos as funções 10.000 vezes somando um mesmo valor.
Para o exemplo seguinte, o retorno da soma foi utilizado como reentrada das funções gerando as seguintes informações:
tBigNumber():Add()
|
SomaStr()
|
| Iterações | 10 |
| tBigN Elapsed | 00:00:00 |
| SomaStr Elapsed | 00:00:00 |
| Diff tBigN x SomaStr | 00:00:00 |
Para MultStr()
| tBigNumber:Mult x MultStr | "123456789" x "123456789" |
| Iterações | 1.000 |
| tBigN Elapsed | 00:00:01 |
| Value | 15241578750190521 |
| MultStr Elapsed | 00:00:03 |
| Value | 15241578750190521 |
| Diff tBigN x MultStr | 00:00:02 |
Neste primeiro exemplo executamos as funções 1.000 vezes multiplicando um mesmo valor.
Para o exemplo seguinte, o retorno da multiplicação foi utilizado como reentrada das funções gerando as seguintes informações:
tBigNumber():Mult()
|
| tBigN Elapsed(1) | 00:00:00 |
| tBigN Elapsed(2) | 00:00:00 |
| tBigN Elapsed(3) | 00:00:00 |
| tBigN Elapsed(4) | 00:00:00 |
| tBigN Elapsed(5) | 00:00:00 |
| tBigN Elapsed(6) | 00:00:00 |
| tBigN Elapsed(7) | 00:00:00 |
| tBigN Elapsed(8) | 00:00:01 |
| tBigN Elapsed(9) | 00:00:03 |
| tBigN Elapsed(10) | 00:00:11 |
| tBigN Elapsed Total | 00:00:15 |
MultStr()
|
| MultStr Elapsed(1) | 00:00:00 |
| MultStr Elapsed(2) | 00:00:00 |
| MultStr Elapsed(3) | 00:00:00 |
| MultStr Elapsed(4) | 00:00:00 |
| MultStr Elapsed(5) | 00:00:01 |
| MultStr Elapsed(6) | 00:00:02 |
| MultStr Elapsed(7) | 00:00:09 |
| MultStr Elapsed(8) | 00:00:38 |
| MultStr Elapsed(9) | 00:02:36 |
| MultStr Elapsed(10) | 00:10:37 |
| MultStr Elapsed Total | 00:14:03 |
| Iterações | 10 |
| tBigN Elapsed Total | 00:00:15 |
| MultStr Elapsed Total | 00:14:03 |
| Diff tBigN x MultStr | 00:13:48 |
No caso de MultStr a diferença é GRITANTE. Neste caso a recomendação seria utilizar a função de usuário.
Os Códigos utilizados para este exemplo:
1: User Function SomaFoo() 2: 3: Local aT1 := Array(10,3) 4: Local aT2 := Array(10,3) 5: 6: Local cStr := "123456789012345678901234567890"+;
7: "123456789012345678901234567890"+;
8: "123456789012345678901234567890"+;
9: "123456789012345678901234567890"
10: 11: Local cBNStr := cStr 12: Local cMSStr := cStr 13: 14: Local cBnIni 15: Local cBnEnd 16: Local cBnTot 17: Local cMsIni 18: Local cMsEnd 19: Local cMsTot 20: 21: Local i 22: 23: Local oTBN := tBigNumber():New(cBNStr) 24: 25: ConOut("","tBigNumber:ADD x SomaStr","-------------------------------------------------------","")
26: 27: cBnIni := Time() 28: For i := 1 To 10000 29: oTBN:Add( oTBN ):ExactValue() 30: Next i 31: --i 32: cBnEnd := Time()33: ConOut("",;
34: PadR("tBigN Elapsed",21)+;
35: " : "+;
36: (cBnTot:=ElapTime(cBnIni,cBnEnd)),;37: PadR("Iteracoes",21)+;
38: " : "+;
39: LTrim(Str(i)),PadR("Value",21)+;
40: " : "+;
41: oTBN:Add(oTBN):ExactValue()) 42: 43: ConOut("","-------------------------------------------------------","")
44: 45: cMsIni := Time() 46: For i := 1 To 10000 47: SomaStr( cMsStr , cMsStr ) 48: Next i 49: --i 50: cMsEnd := Time()51: ConOut("",;
52: PadR("SomaStr Elapsed",21)+;
53: " : "+;
54: (cMsTot:=ElapTime(cMsIni,cMsEnd)),;55: PadR("Iteracoes",21)+;
56: " : "+;
57: LTrim(Str(i)),;58: PadR("Value",21)+;
59: " : "+;
60: SomaStr(cMsStr,cMsStr)) 61: 62: ConOut("",;
63: PadR("Diff tBigN x SomaStr",21)+;
64: " : "+;
65: ElapTime(cBnTot,cMsTot),PadR("Iteracoes",21)+;
66: " : "+;
67: LTrim(Str(i)),"")
68: 69: ConOut("","-------------------------------------------------------","")
70: 71: cBnIni := Time() 72: For i := 1 To 10 73: aT1[i][1] := Time() 74: ConOut(;75: PadR("Value("+LTrim(Str(i))+")",21)+;
76: " : "+;
77: oTBN:SetValue(oTBN:Add(oTBN):ExactValue()):ExactValue()) 78: aT1[i][2] := Time() 79: ConOut(;80: PadR("tBigN Elapsed("+LTrim(Str(i))+")",21)+;
81: " : "+;
82: (aT1[i][3]:=ElapTime(aT1[i][1],aT1[i][2])),"")
83: Next i 84: --i85: ConOut("")
86: aEval(aT1,{|x,y|ConOut(PadR("tBigN Elapsed("+LTrim(Str(y))+")",21)+" : "+x[3])})
87: cBnEnd := aT1[i][2]88: ConOut("",;
89: PadR("tBigN Elapsed",21)+;
90: " : "+;
91: (cBnTot:=ElapTime(cBnIni,cBnEnd)),;92: PadR("Iteracoes",21)+;
93: " : "+;
94: LTrim(Str(i)),"")
95: 96: ConOut("","-------------------------------------------------------","")
97: 98: cMsIni := Time() 99: For i := 1 To 10 100: aT2[i][1] := Time() 101: ConOut(;102: PadR("Value("+LTrim(Str(i))+")",21)+;
103: " : "+;
104: (cMsStr:=SomaStr(cMsStr,cMsStr))) 105: aT2[i][2] := Time() 106: ConOut(;107: PadR("SomaStr Elapsed("+LTrim(Str(i))+")",21)+;
108: " : "+;
109: (aT2[i][3]:=ElapTime(aT2[i][1],aT2[i][2])),"")
110: Next i 111: --i112: ConOut("")
113: aEval(aT2,{|x,y|ConOut(PadR("SomaStr Elapsed("+LTrim(Str(y))+")",21)+" : "+x[3])})
114: cMsEnd := aT2[i][2]115: ConOut("",;
116: PadR("SomaStr Elapsed",21)+;
117: " : "+;
118: (cMsTot:=ElapTime(cMsIni,cMsEnd)),PadR("Iteracoes",21)+;
119: " : "+;
120: LTrim(Str(i)),"")
121: 122: ConOut("",;
123: PadR("Diff tBigN x SomaStr",21)+;
124: " : "+;
125: ElapTime(cBnTot,cMsTot),PadR("Iteracoes",21)+;
126: " : "+;
127: LTrim(Str(i)),"")
128: 129: ConOut("","-------------------------------------------------------","")
130: 131: Return(NIL) 1: User Function MultFoo() 2: 3: Local aT1 := Array(10,3) 4: Local aT2 := Array(10,3) 5: 6: Local cStr := "123456789"
7: 8: Local cBNStr := cStr 9: Local cMSStr := cStr 10: 11: Local cBnIni 12: Local cBnEnd 13: Local cBnTot 14: Local cMsIni 15: Local cMsEnd 16: Local cMsTot 17: 18: Local cConOut 19: 20: Local i 21: 22: Local oTBN := tBigNumber():New(cBNStr) 23: 24: ConOut("","tBigNumber:Mult x MultStr","-------------------------------------------------------","")
25: 26: cBnIni := Time() 27: For i := 1 To 1000 28: oTBN:Mult( oTBN ):ExactValue() 29: Next i 30: --i 31: cBnEnd := Time()32: ConOut("",;
33: PadR("tBigN Elapsed",21)+;
34: " : "+;
35: (cBnTot:=ElapTime(cBnIni,cBnEnd)),PadR("Iteracoes",21)+;
36: " : "+;
37: LTrim(Str(i)),PadR("Value",21)+;
38: " : "+oTBN:Mult(oTBN):ExactValue())
39: 40: ConOut("","-------------------------------------------------------","")
41: 42: cMsIni := Time() 43: For i := 1 To 1000 44: MultStr( cMsStr , cMsStr ) 45: Next i 46: --i 47: cMsEnd := Time()48: ConOut("",;
49: PadR("MultStr Elapsed",21)+;
50: " : "+;
51: (cMsTot:=ElapTime(cMsIni,cMsEnd)),;52: PadR("Iteracoes",21)+;
53: " : "+LTrim(Str(i)),;
54: PadR("Value",21)+;
55: " : "+MultStr(cMsStr,cMsStr))
56: 57: ConOut("",;
58: PadR("Diff tBigN x MultStr",21)+;
59: " : "+;
60: ElapTime(cBnTot,cMsTot),PadR("Iteracoes",21)+;
61: " : "+;
62: LTrim(Str(i)),"")
63: 64: ConOut("","-------------------------------------------------------","")
65: 66: cBnIni := Time() 67: For i := 1 To 10 68: aT1[i][1] := Time() 69: ConOut(;70: PadR("Value("+LTrim(Str(i))+")",21)+;
71: " : "+;
72: oTBN:SetValue(oTBN:Mult(oTBN):ExactValue()):ExactValue()) 73: aT1[i][2] := Time() 74: ConOut(;75: PadR("tBigN Elapsed("+LTrim(Str(i))+")",21)+;
76: " : "+;
77: (aT1[i][3]:=ElapTime(aT1[i][1],aT1[i][2])),"")
78: Next i 79: --i80: ConOut("")
81: aEval(aT1,{|x,y|ConOut(PadR("tBigN Elapsed("+LTrim(Str(y))+")",21)+" : "+x[3])})
82: cBnEnd := aT1[i][2]83: ConOut("",;
84: PadR("tBigN Elapsed",21)+;
85: " : "+;
86: (cBnTot:=ElapTime(cBnIni,cBnEnd)),PadR("Iteracoes",21)+;
87: " : "+;
88: LTrim(Str(i)),"")
89: 90: ConOut("","-------------------------------------------------------","")
91: 92: cMsIni := Time() 93: For i := 1 To 10 94: aT2[i][1] := Time() 95: ConOut(;96: PadR("Value("+LTrim(Str(i))+")",21)+;
97: " : "+;
98: (cMsStr:=MultStr(cMsStr,cMsStr))) 99: aT2[i][2] := Time() 100: ConOut(;101: PadR("MultStr Elapsed("+LTrim(Str(i))+")",21)+;
102: " : "+;
103: (aT2[i][3]:=ElapTime(aT2[i][1],aT2[i][2])),"")
104: Next i 105: --i106: ConOut("")
107: aEval(aT2,{|x,y|ConOut(PadR("MultStr Elapsed("+LTrim(Str(y))+")",21)+" : "+x[3])})
108: cMsEnd := aT2[i][2]109: ConOut("",;
110: PadR("MultStr Elapsed",21)+;
111: " : "+;
112: (cMsTot:=ElapTime(cMsIni,cMsEnd)),;113: PadR("Iteracoes",21)+;
114: " : "+;
115: LTrim(Str(i)),"")
116: 117: ConOut("",;
118: PadR("Diff tBigN x MultStr",21)+;
119: " : "+;
120: ElapTime(cBnTot,cMsTot),PadR("Iteracoes",21)+;
121: " : "+;
122: LTrim(Str(i)),"")
123: 124: ConOut("","-------------------------------------------------------","")
125: 126: Return(NIL)
[]s
иαldσ dj
Comentários
Postar um comentário