Histórico da Página
Pagetitle | ||||
---|---|---|---|---|
|
No exemplo abaixo, imagine que criamos uma função de Hashing "pesada" ... onde para determinar um Hash de uma determinada palavra, são necessárias mais de 256 mil calculos por palavra. E temos uma lista de palavras para calcular o "SuperHash". Usando tabelas temporárias compartilhadas, conseguimos criar uma fila para alguns jobs (a gosto do freguês ou da capacidade da máquina) para cada job processar uma palavra.
Bloco de código |
---|
/* Exemplo de criação de fila de processamento */
user function MyHash()
Local cTable
Local aStru := {}
Local nI, nTimer
Local nJobs := 3
aadd(aStru,{"PALAVRA","C",20,0})
aadd(aStru,{"JOBID","C",2,0})
aadd(aStru,{"HEXHASH","C",40,0})
aadd(aStru,{"TEMPO","N",12,3})
tclink()
DbCreate("%SHTMP%",aStru,"TOPCONN")
cTable := tcconfig("GETTEMPNAME=%SHTMP%")
// 7 palavras para processamento
aPalavras := {}
aadd(aPalavras,"ARQUIPELAGO")
aadd(aPalavras,"AUTOMOVEL")
aadd(aPalavras,"ONIBUS")
aadd(aPalavras,"PARALELEPIPEDO")
aadd(aPalavras,"BETERRABA")
aadd(aPalavras,"PTERODACTILO")
aadd(aPalavras,"CHEWBACCA")
// abre a tabela
USE (cTable) ALIAS TMP SHARED NEW VIA "TOPCONN"
// acrescenta as palavras no arquivo
aeval( aPalavras , { |x| dbappend(), TMP->PALAVRA := x , dbrunlock() })
// Limpa variavel global de controle
PutGlbValue("PROCJOBS","")
// Inicia os jobs
For nI := 1 to nJobs
StartJob("U_JOBHASH",getenvserver(),.f.,strzero(nI,2),cTable)
Sleep(100)
Next
// Inicia contagem de tempo
nTimer := seconds()
// Espera os jobs terminarem
MsgRun("Calculando Hashes","Aguarde ... ",{|| WaitProcs(nJobs) } )
// Mostra os dados processados
// lendo a propria tabela
DBGotop()
While !eof()
conout(TMP->PALAVRA+" => "+TMP->HEXHASH+' (JOB '+TMP->JOBID+') em '+str(TMP->TEMPO,12,3)+' s.')
DbSkip()
Enddo
// Fecha a tabela
DbCloseArea()
// Apaga a tabela
TcDelFile(cTable)
MsgInfo("Tempo Total : "+str(seconds()-nTimer,12,3)+" s.","Atenção")
return
// Espera o processamento estar temrinado
// Usa uma variavel global em memoria para controle
STATIC Function WaitPRocs(nJobs)
Local cOk := replicate(".",nJobs)
While !killapp() .and. GetGlbValue("PROCJOBS") != cOk
Sleep(250)
Enddo
RETURN
// Job de processamento
// Recebe o nome da tabela, processa os dados pendentes
// Ao temrinar , acrescenta um "." na global de controle
USER Function JOBHASH(cIdJob,cTable)
Local cPalavra, cJobRun
Local cRet
Local nTimer
tclink()
USE (cTable) ALIAS TMP SHARED NEW VIA "TOPCONN"
While !Eof()
cPalavra := Alltrim(TMP->PALAVRA)
cJobRun := TMP->JOBID
IF dbrlock(recno())
// Se bloqueou , pode processsar
// mas verifica se já nao está processado ...
If !empty(TMP->HEXHASH)
conout("Job ["+cIdJob+"] ["+cPalavra+"] foi processada pelo Job ["+cJobRun+"]")
dbrunlock()
dbskip()
LOOP
Endif
conout("Job ["+cIdJob+"] ["+cPalavra+"] sendo calculado ... aguarde ...")
// Atualiza o JobId que está processando esse registro
// e faz flush da informação pro banco de dados
TMP->JOBID := cIdJob
DBCommit()
nTimer := seconds()
cRet := SuperHash(cPalavra)
conout("Job ["+cIdJob+"] ["+cPalavra+"] calculado em "+str(seconds()-nTimer,12,3)+" s.")
// atualiza no registro o hash calculado
// e o tempo que demorou
TMP->HEXHASH := cRet
TMP->TEMPO := round(seconds()-nTimer,3)
// e Solta o bloqueio
Dbrunlock()
else
// Nao bloqueou , esta sendo processada por outro job
conout("Job ["+cIdJob+"] ["+cPalavra+"] ignorada -- em processamento pelo Job ["+cJobRun+"] ")
Endif
// Vai para o proximo
DbSkip()
ENDDO
PutGlbValue("PROCJOBS",GetGlbValue("PROCJOBS")+'.')
DbCloseArea()
RETURN
// Aplica SHA1 262144 para cada palavra
// retorna SHA1 no formato hexadecimal ( 40 caracteres )
STATIC function SuperHash(cPalavra)
Local nI
For nI := 1 to 256 * 1024
cPalavra := SHA1(cPalavra,2)
Next
RETURN cPalavra
|
...
Agora , ao colocarmos 3 jobs processando, podemos ter um resultado assim:
Bloco de código |
---|
Job [01] [ARQUIPELAGO] sendo calculado ... aguarde ...
Job [02] [ARQUIPELAGO] ignorada -- em processamento pelo Job [01]
Job [02] [AUTOMOVEL] sendo calculado ... aguarde ...
Job [03] [ARQUIPELAGO] ignorada -- em processamento pelo Job [01]
Job [03] [AUTOMOVEL] ignorada -- em processamento pelo Job [02]
Job [03] [ONIBUS] sendo calculado ... aguarde ...
Job [01] [ARQUIPELAGO] calculado em 3.169 s.
Job [01] [AUTOMOVEL] ignorada -- em processamento pelo Job [02]
Job [01] [ONIBUS] ignorada -- em processamento pelo Job [03]
Job [01] [PARALELEPIPEDO] sendo calculado ... aguarde ...
Job [03] [ONIBUS] calculado em 3.161 s.
Job [03] [PARALELEPIPEDO] ignorada -- em processamento pelo Job [01]
Job [03] [BETERRABA] sendo calculado ... aguarde ...
Job [02] [AUTOMOVEL] calculado em 3.321 s.
Job [02] [ONIBUS] foi processada pelo Job [03] <===== REPARE AQUI
Job [02] [PARALELEPIPEDO] ignorada -- em processamento pelo Job [01]
Job [02] [BETERRABA] ignorada -- em processamento pelo Job [03]
Job [02] [PTERODACTILO] sendo calculado ... aguarde ...
Job [01] [PARALELEPIPEDO] calculado em 3.413 s.
Job [01] [BETERRABA] ignorada -- em processamento pelo Job [03]
Job [01] [PTERODACTILO] ignorada -- em processamento pelo Job [02]
Job [01] [CHEWBACCA] sendo calculado ... aguarde ...
Job [03] [BETERRABA] calculado em 3.405 s.
Job [03] [PTERODACTILO] ignorada -- em processamento pelo Job [02]
Job [03] [CHEWBACCA] ignorada -- em processamento pelo Job [01]
Job [02] [PTERODACTILO] calculado em 3.411 s.
Job [02] [CHEWBACCA] ignorada -- em processamento pelo Job [01]
Job [01] [CHEWBACCA] calculado em 2.813 s.
ARQUIPELAGO => 53be976968beeb949b9e17515b388ff1be51c582 (JOB 01) em 3.169 s.
AUTOMOVEL => abb157df53f6b89befdb93084b3855c9b89752b2 (JOB 02) em 3.321 s.
ONIBUS => 9ca3cf8e0d8030ffd85a62782ccafd047cf80bca (JOB 03) em 3.161 s.
PARALELEPIPEDO => 797525c9c858a969417569ff9dc309a9a7b245ad (JOB 01) em 3.413 s.
BETERRABA => 667320efb1e4194f125b2139448a04d897bf9f8d (JOB 03) em 3.405 s.
PTERODACTILO => 4891a5682a28f4472531a05387d51bd43cdb7874 (JOB 02) em 3.411 s.
CHEWBACCA => 8122c6c9720adb5971b57468766ce32efdb71140 (JOB 01) em 2.813 s.
|
...
Visão Geral
Import HTML Content
Conteúdo das Ferramentas
Tarefas