Pular para o conteúdo principal

Postagem em destaque

BlackTDN :: LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring

_Créditos das imagens: ChatGPT_ ### LeetCode :: Comparando Implementações Harbour e TLPP para o Desafio Longest Palindromic Substring Resolver o problema do [Longest Palindromic Substring](https://leetcode.com/problems/longest-palindromic-substring/description/) é um exercício clássico de programação, que desafia desenvolvedores a encontrar a maior substring palindrômica dentro de uma string. Recentemente, exploramos soluções tanto em Harbour quanto em TLPP (Total Language Protheus Programming). Neste artigo, comparamos as implementações nessas duas linguagens, destacando suas semelhanças, diferenças e funcionalidades específicas. #### Implementações em Harbour ##### Versão 5.1 Essa solução utiliza a técnica de expansão a partir do centro do palíndromo. Cada caractere ou par de caracteres consecutivos é considerado um possível "centro". O algoritmo expande em ambas as direções enquanto os caracteres forem iguais, retornando o maior palíndromo encontrado. ##### Versão 5....

Protheus :: Advpl : Processamento em Grid e Multi Thread – Números Perfeitos : Versão Final

Números Perfeitos foi totalmente reescrito para trabalhar usando o “Processamento em Grid” e “Multi Thread”.  Agora, parafraseando Ernesto Haberkorn, “Dividimos para Multiplicar”.

O uso do Processamento em Grid no Protheus é, de fato, bem simples, mas a forma de Programar e de controle, torna-se um tanto quanto “complicada” (o mesmo podemos dizer para o uso de “Multi Thread”). Números Perfeitos pretende ser um exemplo claro e simples do uso desses dois “paradigmas”. Usará ambos quando a configuração do Processamento em Grid estiver definido ou apenas o último, caso contrário.

Para começar a programar usando Processamento em Grid, primeiro, precisei entender e aprender como o Processamento em Grid foi programado em ADPL. Identifiquei a existência de uma Classe: GridClient e, considerando que por padrão, em ADVPL, todas as Classes são instanciadas com o Método :New(), utilizei as seguintes funções ClassDataArr()  e ClassMethArr() para me auxiliar a entender as Propriedades da Classe e seus Métodos. ClassDataArr( GridClient():New() )  retornou todas as Propriedades da Classe GridClient e ClassMethArr( GridClient():New() )  todos os métodos que eu poderia utilizar.

Dentre os Métodos retornados, os que me interessaram foram:

:New() : Instancia um novo objeto da Classe GridClient;

:ConnectCoord() : Verifica a configuração do Processamento em Grid e, se tudo ok, efetua a conexão entre os “Agents” e o “Coordinator”;

:GetError() : Retorna a última mensagem de erro;

:GetIdleThreads() : Retorna o número de Threads em estado “IDLE”;

:BatchExec() : Efetua e gerencia o Processamento em Grid;

:WaitReceiveAll() : Verifica se todos os Retornos foram Recebidos;

:Terminate() : Utilizado para verificar se todos os processos da Grid Terminaram corretamente ou Para forçar a Finalização; e

Dentre as Propriedades:

:lGridFinish : Identifica se o Processo foi Terminado.

Obviamente que todos os comentários acima não passam de inferência, uma vez que não encontrei Documentação Completa sobre a Classe. No “Chute” e “Tentativa e Erro” pude identificar as características de cada um.

Além de ClassDataArr()  e ClassMethArr(),  __FunArr() auxiliou-me na identificação de algumas funções para uso no exemplo tornando-o um pouco mais rico. Dentre elas: GetServerIP(), GetSrvIniName() (antes utilizava GetAdv97() para retornar o nome do arquivo INI de configuração do Protheus Server), ThreadId() , GetEnvServer() e PTInternal().

A afirmativa de que o Processamento em Grid no Protheus é bem simples pode ser comprovada com o fragmento de código abaixo:

//Instancio um Novo Objeto da Classe GridClient

oGClient := GridClient():New()

//Verifico se é possível Conectar-se

IF !( oGClient:ConnectCoord() )

   //Capturo o Erro se a conexão não for possível

   ConOut( oGClient:GetError() )

EndIF

//Tento executar

IF !(oGClient:BatchExec("U_GMathPEnv",@aGPPEnv,"U_GMathCall",@aGPCall,"U_GMathEnd"))

//Capturo o último Erro ocorrido durante o Processamento.

ConOut( oGClient:GetError() )

EndIF

O método BatchExec espera, em seus parâmetros formais o seguinte:

BatchExec( cFnPrepEnv , aPrmPrepEnv  , cFnCallGrid , aPrmCallGrid , cFnEndGrid ):

cFnPrepEnv : Função ADVPL a ser executada para a Preparação do Ambiente

aPrmPrepEnv: Array com os Parâmetros da Função de Preparação do Ambiente

cFnCallGrid: Função ADVPL para Processamento em Grid

aPrmCallGrid: Array com os Parâmetros da Função de Processamento em Grid

cFnEndGrid: Função em ADVPL a ser executada na Finalização do Processo em Grid

GRID_CLIENT_NEWGRID_CLIENT_BATCHEXEC 

Simples assim.

E, para o “Multi Thread” também. Neste caso, usaremos a função StartJob(). StartJob possui os seguintes parâmetros formais:

StartJob( cADVPLFun , cEnvironment , lWaitRun , < [param1, …paramN] > ), onde:

cADVPLFun : Função em Advpl a ser Executada ( Obrigatório )

cEnvironmet : Ambiente a ser utilizado ( Obrigatório )

lWaitRun : Se .T. aguarda até que o processamento seja concluído e seu retorno será o retorno real da função passada como parâmetro em cADVPLFun;

< [param1, …paramN] > : Parâmetros ( Opcional ) a serem passados para a função a ser Executada conforme cADVPLFun

U_GMathIPNum() é mais rica na exploração de ambas.

Bem, agora que já vimos, através de fragmentos de código, como o “Processamento em Grid” e “Multi Thread” são via ADVPL, vamos a configuração.

Para o processo em “Multi Thread” nenhuma configuração adicional se faz necessária, mas para o “Processamento em Grid” teremos:

Grid de processamento AdvPL – Configuração (referência tdn: http://tdn.totvs.com.br/kbm#30760)

No Grid Server (Coordinator)

[ONSTART]
Jobs=GridServer
RefreshRate=60
[GridServer]
Main=GridServer
Environment=PTGrid

[GridAgent]
Main=GridAgent
AgentIp=protheus
AgentPort=4020
Instances=15
Environment=PTGrid
CoordServer=protheus
CoordPort=4020

Por Algum motivo, a configuração do GridAgent no “Coordinator” é obrigatória.

No Grid Client (Agent)

[ONSTART]
JOBS=GridAgent
RefreshRate=15


[GridAgent]
Main=GridAgent
AgentIp=protheus
AgentPort=4021
Instances=15
Environment=PTGrid
CoordServer=protheus
CoordPort=4020

Ao contrário da configuração do “Load Balance”, onde o servidor “Master” identifica os “Slaves”, no “Processamento em Grid” são os “Agentes” que se Identificam ao “Coordinator”.

Pode-se utilizar os mesmos serviços Protheus utilizados na configuração do “Load Balance” (e é recomendado) mas não necessário. Qualquer serviço protheus que se comunique com o “Coordinator” pode ser um “Agent”. Poderemos ter tantos “Agents” quantos necessários. Para testar “Números Perfeitos” usei o PC de casa. Cinco serviços do Protheus escutando nas portas 4020 a 4024 sendo:

O servidor “Principal” (Master ou Coordinator)

[ServerNetWork]
Servers=Slave01,Slave02,Slave03,Slave04
MasterConnection=0

[Slave01]
Type=TCPIP
Server=protheus
Port=4021
Connections=30

[Slave02]
Type=TCPIP
Server=protheus
Port=4022
Connections=30

[Slave03]
Type=TCPIP
Server=protheus
Port=4023
Connections=30

[Slave04]
Type=TCPIP
Server=protheus
Port=4024
Connections=30

[ONSTART]
Jobs=GridServer
RefreshRate=60
[GridServer]
Main=GridServer
Environment=PTGrid

[GridAgent]
Main=GridAgent
AgentIp=protheus
AgentPort=4020
Instances=15
Environment=PTGrid
CoordServer=protheus
CoordPort=4020

e, os Slaves ou Agents ( de 4021 a 4024 ):

[ONSTART]
JOBS=GridAgent
RefreshRate=15


[GridAgent]
Main=GridAgent
AgentIp=protheus
AgentPort=4021 ; de 4021 a 4024
Instances=15
Environment=PTGrid
CoordServer=protheus
CoordPort=4020

Feita a configuração, basta compilar os programas do exemplo e executar a função U_GMathIPNum().

Uma Dica, “Depurar” um programa “Multi Thread” não é nada fácil, mas, para ativar a “Depuração” marque, no IDE do Protheus, e para o ambiente que deseja depurar, a opção: “Permitir depuração de múltiplas threads” (Arquivo\Configuração Selecione o Ambiente, botão Editar, Aba Geral).

IDE_MTHREAD

Para que o IDE possa “capturar” uma “Thread” para “Depuração” ele precisa estar em “Modo Debug”.

IDE_DEBUG_MODE

IDE_DEBUG_MODE_IMAGE

Que é Ativado quando executamos qualquer função pelo IDE, mesmo que inválida, como, por exemplo: MsgInfo

IDE_DEBUG_MODE_MSGINFO

Para não ficar maluco, procure garantir que apenas uma “Thread” esteja ativa durante o “Processo de  Depuração”.

Para monitorar o “Processamento em Grid” use o TotvsMonitor ou o Monitor conforme instantâneo abaixo:

MONITOR

Muitas informações do “Processamento em Grid” são enviadas para o Console do Protheus e para o seu arquivo de LOG, conforme abaixo:

CONSOLE_LOG 

Considerando que para a apuração dos “Números Perfeitos” utilizamos a Classe TMathIntegerStr, se baixar os arquivos dessa classe terá, também, a última versão de “Números Perfeitos”, agora no arquivo U_GMathINPerfeito.prg. Baixe a última versão das Classes TMath[I/S]Str, compile o Projeto e execute U_GMathIPNum() para ver o funcionamento do “Processamento em Grid” e “Mult Thread” no Protheus.

Poderá obtê-la ao clicar aqui.

Post Scriptum: “Números Perfeitos”, além de uma curiosidade matemática, pode leva-lo ao “Livro dos Records”. Encontre um “Número Perfeito” com mais de 25.956.377 algarismos e seja reconhecido mundialmente. Além da curiosidade matemática e da possibilidade de torna-lo “famoso” “Números Perfeitos” pode ser útil para avaliar o desempenho dos seus servidores no que diz respeito ao uso do Protheus.

Curiosidade Matemática: Euclides e os “Números Perfeitos”

[]s
иαldσ dj

Comentários

  1. Parabens denovo!
    Vou aplicar este exemplo para testar o desempenho dos meus servidores.
    Estamos prestes a fazer um upgrade e sera bacana para mensurar o ganho de performance... :)
    Vlw Naldo.

    ResponderExcluir
  2. Cara, fica até chato comentar no seu blog.
    Porque sempre é para escrever a mesma coisa...

    PARABENS PELA PESQUISA, PELO APRENDIZADO E POR DIVIDIR PARA CONQUISTAR.

    Chega aí em BH e vamos tomar uma GELA e queimar umas carnes!

    GTalk!

    ResponderExcluir
  3. GTalk!!!

    Hehe, demorô!!! vamos pras brejas.....

    []s
    иαldσ dj

    ResponderExcluir
  4. Ferne$,

    Tente aumentar os valores das constantes abaixo (faça o server trabalhar) e diga-nos como o Protheus se saiu. Será que Protheus será páreo para "Números Perfeitos" ou vai pedir arrego?


    #DEFINE NP_GRID "10" //Informe um Numero Par
    #DEFINE NP_THREAD 5 //Numero de Threads Concorrentes
    #DEFINE NP_MAXZERO 25 //0000000000000000000000000 | How big do you want?
    #DEFINE NP_MAXNUMP ( NP_MAXZERO + 1 ) //10000000000000000000000000 | MASK: 10.000.000.000.000.000.000.000.000

    E.T.: Tem uma nova versão disponível para download.

    []s
    иαldσ dj

    ResponderExcluir
  5. Camo faço para baixar o exemplo U_GMathINPerfeito.prg, não esta mais disponivel

    ResponderExcluir
  6. André, é só seguir o link https://docs.google.com/leaf?id=0BxUwnVt68UewN2FjYTEyNzItZGE1ZC00NTk0LWFkYzAtYTRlODQ4MjI2MjQ1&sort=name&layout=list&num=50 ou clicar no "aqui" do post. Irá redirecionar para o Google Docs. No Lado Superior Direito da "Janela" do Browser irá aparecer um botão "Download"

    []s
    Naldo.

    P.S.: Estou pensando em reescrever Números Perfeitos e as classes matemáticas no Harbour. Usando toda técnica orientada a objeto: inclusive Sobrecarga de operadores (uma coisa que não tem no protheus)

    ResponderExcluir
  7. melhor dizendo, Advpl é que não possibilita a Sobrecarga de Operadores e muitos outros recursos de OO.

    ResponderExcluir
  8. Bom dia, tem como postar a configuração do IDE para debugar, não estou conseguindo configurar

    ResponderExcluir

Postar um comentário

Postagens mais visitadas