Página 3 de 5

Copia com barra de progresso.

Enviado: 23 Nov 2013 23:14
por cjp
De fato, não tinha atentado para esse detalhe, e até demorei um pouco para entender do que vc estava falando. Já acertei e funcionou. E também já excluí as linhas desnecessárias. Muito obrigado.

Copia com barra de progresso.

Enviado: 23 Nov 2013 23:43
por Toledo
Bom, então só para complementar:

Código: Selecionar todos

aFileInfo := DIRECTORY(cPOrig+"*.*")
Abraços,

Copia com barra de progresso.

Enviado: 23 Nov 2013 23:47
por cjp
Sim, foi exatamente isso que eu fiz e deu certo. Obrigado.

Copia com barra de progresso.

Enviado: 05 Dez 2013 14:53
por cjp
Colegas,

Usando diariamente esta função, notei uma coisa interessante: a cópia de um arquivo de 1,4 GB, usando o !copy, levou exatos 7 minutos e 23 segundos. Já o mesmo arquivo copiado com esta função xhb_copyfile() levou exatos 22 minutos e 22 segundos. Ou seja, cerca de 3 vezes mais.

Isso é normal? Tem alguma razão para ser tão mais lento? Existe alguma solução para isso?

Copia com barra de progresso.

Enviado: 14 Dez 2013 17:18
por cjp
Alguém saberia me dizer se tem alguma razão de demorar tanto assim a cópia desse jeito?

Copia com barra de progresso.

Enviado: 14 Dez 2013 22:57
por JoséQuintas
Tudo depende do seu gráfico.
Só imaginar que a cada byte copiado a função vai ser chamada.
E atualização de tela é mais demorada que cópia.

Copia com barra de progresso.

Enviado: 16 Dez 2013 16:52
por cjp
Hum, e será que tem como chamar a função menos vezes?

Minha função está assim:

Código: Selecionar todos

function CopiarArquivo(cFile,cPasta,cPDest)
 local cSource := cPasta + cFile
 local cTarget := cPDest + cFile
 local lCopy
 local aFileInfo := directory( cPasta + cFile)
 nTotalBytes := aFileInfo[1,2] // size file to copy
 lCopy := xhb_CopyFile(cSource, cTarget, {| x | ShowCopy( x ) }) // Every 8192 Bytes copied
 inkey(5)
return .t.

function ShowCopy(x)
 nCopiados += x
 @ maxrow()-1,1 say ' Copiando :' + str(nCopiados/1048576) + ' de ' + str(nTotalBytes/1048576) + " Mb"
return nil

Quem sabe poderia atualizar a cada 10 Mb, por exemplo, para acelerar a função.

Copia com barra de progresso.

Enviado: 16 Dez 2013 17:45
por JoséQuintas
Eu uso um estilo padrão, pra atualizar tela a cada 1 segundo.
Faça o teste se ajuda.

Código: Selecionar todos

FUNCTION ShowGrafico()
   STATIC cTime := "XX"

   IF cTime == Time()
       RETURN NIL
   ENDIF
   cTime := Time()
   // mostra grafico
   RETURN NIL

Copia com barra de progresso.

Enviado: 16 Jan 2014 22:01
por cjp
Desculpem a demora, estive afastado e só agora retornei.

Fiz vários testes, mas aparentemente não é esse o problema.

Testando com um arquivo de 930 MB, se coloco para atualizar a cada 5 segundos, demorou 9 minutos e 32 segundos; se coloco para atualizar a cada 10 segundos, demorou 9 minutos e 27 segundos. Mas copiando com o !copy, demorou apenas 3 minutos e 24 segundos.

Será que o problema não está na própria xhb_copyfile()?

Copia com barra de progresso.

Enviado: 17 Jan 2014 08:51
por Toledo
cjp escreveu:// Every 8192 Bytes copied
Como é observado no exemplo de uso da função xhb_CopyFile(), o arquivo é copiado a cada 8192 bytes. Então para acelerar a função poderia tentar aumentar o número de bytes copiados, mas para fazer isto você teria que ter os arquivos fontes da LIB xhb (pasta ..\CONTRIB\XHB) e editar o arquivo xhbcopyf.c, modificando o valor da variável BUFFER_SIZE:

Código: Selecionar todos

#define BUFFER_SIZE 8192
Você pode duplicar o valor, por exemplo: #define BUFFER_SIZE 16384

Depois é só recompilar a LIB novamente.

Abraços,

Copia com barra de progresso.

Enviado: 17 Jan 2014 09:00
por JoséQuintas
Aproveitando o gancho...
A lentidão no uso de DBFs é exatamente pelo mesmo motivo: o tamanho do "buffer" vai ser o tamanho do registro.
Então um relatório, ou um set filter, fica lento principalmente em rede.
Mesmo que a rede seja gigabit, a transferência vai ser por blocos pequenos.

É nisso que o servidor de banco de dados também ganha do dbf: Transfere em blocos maiores.

Copia com barra de progresso.

Enviado: 17 Jan 2014 11:37
por cjp
Toledo, como faço para recompilar a lib?

Desculpe minha ignorância, mas nunca fiz isso.

Copia com barra de progresso.

Enviado: 17 Jan 2014 12:03
por Toledo
cjp, primeiramente você tem que ter os código fontes da LIB, então verifique se na pasta ..\CONTRIB\XHB do seu Harbour tem o arquivo xhbcopyf.c.

Se o arquivo xhbcopyf.c existir, para recompilar basta seguir as orientações do arquivo INSTALL que está na pasta principal do seu Harbour:
2. HOW TO DO A PARTIAL [RE]BUILD
================================

If you want to [re]build only a specific part of Harbour, like
one core library or all core libraries, or all contrib packages,
you have to do everything the same way as for a full build, the
only difference is that you first have to go into the specific
source directory you want to [re]build. When starting GNU Make,
all components under that dir will be [re]built:

cd src/rtl
<make> [clean] [install]

If you want to rebuild one specific contrib package, use this:

cd contrib/<name>
../../bin/<plat>/<comp>/hbmk2 ../make.hb [clean] [custom hbmk2 options]
Conforme orientação acima, você teria que entrar na pasta ..\CONTRIB\XHB do seu Harbour e digitar:

HBMK2 ../make.hb clean

Abraços,

Copia com barra de progresso.

Enviado: 17 Jan 2014 13:04
por Itamar M. Lins Jr.
Aproveitando o gancho...
A lentidão no uso de DBFs é exatamente pelo mesmo motivo: o tamanho do "buffer" vai ser o tamanho do registro.
Então um relatório, ou um set filter, fica lento principalmente em rede.
Mesmo que a rede seja gigabit, a transferência vai ser por blocos pequenos.

É nisso que o servidor de banco de dados também ganha do dbf: Transfere em blocos maiores.
Isso pode ser corrigido, porém tem uma coisa mais importante que é o Harbour 32 e outro Harbour 64, segundo o Pzmek o ganho de velocidade é bem maior, desde que todas as rotinas estejam ajustadas para 64bits! e o Harbour já pode ser compilado em 64Bits.
Hi,

> Would an application compiled as 64 bit by Harbour operate faster on
> a 64 bit machine vs the same application compiled as 32 bit on the
> same 64 bit machine?

Yes it will. Mostly due to the cost of switching between kernel and
user space. In 64 bit mode we have extremely huge address space so
it's possible to set fixed addresses for user space and kernel space
and never reload memory descriptors when execution context is changed.
Here depending on the OS and type of application )how many times
system functions are called) the speed difference can be quite huge.
Additional speed up is also reached due to wider set of machine
instructions and completely new C ABI which uses extended 64-bit
registers to pass parameters when C functions are called. This
gives about 10-15% speed improvement in case of Harbour HVM.

best regards,
Przemek
Então não é porque usamos DBF e sim por causa da arquitetura adotada, cliente servidor é o que deve ser adotado.
Olhe o custo do ADS por exemplo que usa DBF e é extremamente rápido inclusive com uso de sintaxe SQL.
Ou então olhe esse código do Letodb que é executado do lado do servido, simulando o (foreign key)

Código: Selecionar todos

/*
 * UDF_UpdCascade - cascade update key fields in main and relation table
 * Parameters:
 *   nRecNo       - record number in the main table
 *   cKeyField    - field name in the main table (primary key)
 *   xKeyNew      - new value of key field
 *   cClientAlias - client alias of the relation table
 *   cKeyField2   - field name in the relation table (foreign key)
 *   xOrder       - order name or order number in the relation table
 *
 * This function return array of record buffer in two tables
 * Call from client:
 *
 * aRecBuf := Leto_Udf("UDF_UpdCascade", ... )
 * (table1)->( leto_ParseRec( aRecBuf[1] ) )
 * (table2)->( leto_ParseRec( aRecBuf[2] ) )
 */
FUNCTION UDF_UpdCascade( nUserStru, nRecNo, cKeyField, xKeyNew, cClientAlias, cKeyField2, xOrder )
   LOCAL xKeyOld, cLetoAlias, cArea := Alias()
   LOCAL nPos := FieldPos( cKeyField ), nPos2
   LOCAL cRecBuf1, cRecBuf2

   dbGoto( nRecNo )
   xKeyOld := FieldGet( nPos )
   IF xKeyOld != xKeyNew .and. leto_RecLock( nUserStru, nRecNo )
      FieldPut( nPos, xKeyNew )
      leto_RecUnlock( nUserStru, nRecNo )
      cRecBuf1 := leto_rec( nUserStru )

      cLetoAlias := leto_Alias( nUserStru, cClientAlias )
      dbSelectArea( cLetoAlias )
      IF Empty( cKeyField2 )
         cKeyField2 := cKeyField
      ENDIF
      nPos2 := FieldPos( cKeyField2 )
      IF ! Empty( xOrder )
         ordSetFocus( xOrder )
      ENDIF
      WHILE dbSeek( xKeyOld )
         IF leto_RecLock( nUserStru, RecNo() )
            FieldPut( nPos2, xKeyNew )
            leto_RecUnlock( nUserStru, RecNo() )
         ELSE
            EXIT
         ENDIF
      ENDDO
      dbSeek( xKeyNew )
      cRecBuf2 := leto_rec( nUserStru )

      dbSelectArea( cArea )

   ENDIF
   RETURN { cRecBuf1, cRecBuf2 }
Se usarmos em uma REDE sem servidor, provavelmente ficaria muito lento e perigoso, porém este código é executado no servidor, pelo "DAEMON" letodb
E também podemos usar um servidor LINUX via SSH, que fica muito rápido e corrupção de DBF´s praticamente 0%.


Saudações,
Itamar M. Lins Jr.

Copia com barra de progresso.

Enviado: 17 Jan 2014 15:18
por cjp
Toledo, não tenho o arquivo xhbcopyf.c na pasta contrib\xhb. Como faço para obtê-lo?