An example of multithreading and Database

An example of multithreading and Database

Postby vilian » Tue Aug 26, 2014 2:32 pm

Hi,

Does anyone have an example of using WorkAreas and MT?
Sds,
Vilian F. Arraes
vilian@vfatec.com.br
Belém-Pa-Brazil
User avatar
vilian
 
Posts: 920
Joined: Wed Nov 09, 2005 2:17 am
Location: Brazil

Re: An example of multithreading and Database

Postby thefull » Tue Aug 26, 2014 3:18 pm

https://docs.google.com/document/d/1xxR ... 0MVg/edit#

Example multiThread index.
I want it noticed that it is possible to use MultiThread in index, but, in practice, in most cases it won't cause speed up because the bottleneck is not the CPU.
So read for better understanding of MultiThread

Code: Select all  Expand view

/*
  Example multiThreads index.
  One thread by table , and one thread by index.
  2010 Rafa Carmona

  Thread Main
       |--------->  Thhread child table for test.dbf
       |                        |----> Thread child index fname
       |                        |
       |                        |----->Thread child index fcode
       |
       |--------->  Thhread child table for test2.dbf
                               |----->Thread child index fname2


 */

#include "hbthread.ch"

proc Main( uCreate )
   Local nSeconds
   Local aFiles  := { "test", "test2" }        // Arrays files dbf
   Local aNtx    := { { "fname", "fcode" },;   // files index for test
                      { "fName2" } }           // files index for test2
   Local aExpr   := { { "name", "code" },;
                      { "dtos(fecha)+str(code)" }  }     // Expresions
   Local cDbf

   if empty( lCreate )
      lCreate := "0"
   endif

   setmode( 25,80 )
   cls

   if uCreate = "1"
      ? "Create test.dbf and test2.dbf"
      dbCreate("test",{ {"name","C",1,0 },{"code","N",7,0 } } )
      use test
      while lastRec() < 1000000
            dbAppend()
            field->name := chr( recno() )
            field->code := recno()
      enddo
      close
      dbCreate("test2",{ {"fecha","D",8,0 },{"code","N",7,0 } } )
      use test2
      while lastRec() < 1000000
            dbAppend()
            field->fecha := date() + recno()
            field->code := recno()
      enddo
      close
   endif

   cls
   // Threads
   nSeconds := Seconds()
   for each cDbf in aFiles
      ? "Process.: " + cDbf
      hb_threadStart( @aCreateIndexe(), cDbf, aNtx[ cDbf:__enumindex ],aExpr[ cDbf:__enumindex ], cDbf:__enumindex  )
   next

   ? "Wait for threads ...."
   hb_threadWaitForAll()

   ? hb_valTostr( Seconds() - nSeconds )

   ? "finish"

return

function aCreateIndexe( cFile, aNtx, aExpr, nPosDbf )
      Local nContador := 1
      Local cFileNtx, cExpr
      Local nLong := Len( aNtx )
      Local aThreads := {}
      Local cAlias

      use ( cFile )
      cAlias := alias()
      hb_dbDetach( cAlias )  // Libero el alias

      for each cFileNtx in aNtx
          cExpr  := aExpr[ cFileNtx:__enumindex ]
          nContador := 1
          nPos := cFileNtx:__enumindex
          aadd( aThreads, hb_threadStart( @crea(), cAlias,cExpr, cFileNtx, nPos, nPosDbf ) )
      next

      aEval( aThreads, { |x| hb_threadJoin( x ) } )  // wait threads childs
      hb_dbRequest( cAlias, , , .T.)  // Restaura el alias
      close

RETURN NIL

proc crea( cAlias, cExpr, cFileNtx, nPos, nPosDbf )
     Local nContador := 1

      hb_dbRequest( cAlias, , , .T.)  // Restaura el alias

      INDEX ON &(cExpr) TO &(cFileNtx) ;
       EVAL {|| hb_dispOutAt( nPosDbf, iif( nPos = 1, 20, 40 ),alltrim( hb_valtostr( nContador) ), "GR+/N" ), nContador += INT(LASTREC() / 100 ) , .T. } ;
       EVERY INT( LASTREC() / 100 )
      hb_dbDetach( cAlias )          // Libera el alias

return
 
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: An example of multithreading and Database

Postby cnavarro » Tue Aug 26, 2014 4:02 pm

Un ejemplo muy bueno que habrá que guardar como "oro en paño"
Gracias Rafa
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6501
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: An example of multithreading and Database

Postby vilian » Tue Aug 26, 2014 5:38 pm

Rafa,

It is possible for one thread to use more than one workarea?
Sds,
Vilian F. Arraes
vilian@vfatec.com.br
Belém-Pa-Brazil
User avatar
vilian
 
Posts: 920
Joined: Wed Nov 09, 2005 2:17 am
Location: Brazil

Re: An example of multithreading and Database

Postby thefull » Wed Aug 27, 2014 2:38 pm

The threads do not limit the amount of open table, otherwise this workarea visibility between threads.
If you open a dbf table in the main thread, the same work area can not be used in a child thread,
for hb_dbRequest () function is used to transfer the alias of a thread to another.
That will not prevent open dbf table in another thread. An example;

Sorry my english is a translation of Google;
"Los hilos no te limitan la cantidad de tabla abiertas, si no, la visibilidad de esa workarea entre hilos.
Si abres una tabla dbf en el hilo principal, esa misma área de trabajo no puedes usar en un hilo hijo,
para se usa la función hb_dbRequest() para traspasar el alias de un hilo a otro.
Eso no te impide, abrir tabla dbf en otro hilo. Un ejemplo;"

SeudoCódigo

Code: Select all  Expand view
Function Main()  
   Open table "customers" alias "customer"
   Go Top

   hb_threadStart( @create_child_thread() )
 
  ? customer->recno()  // First
   hb_threadWaitForAll()

return

function create_child_thread()
   Open table "customers" alias "customer"
   Open table "telephone" alias "telephone"

   Select "customer"  // This work area NOT IS function main
   go bottom
   ? customer->recno() // Last
   
   CLOSE ALL

return nil
 
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: An example of multithreading and Database

Postby thefull » Wed Aug 27, 2014 3:16 pm

cnavarro wrote:Un ejemplo muy bueno que habrá que guardar como "oro en paño"
Gracias Rafa


Ojo, que esto es a nivel 'experimental', y si lanzas esto con 300 tablas y 500 indices, verás como el server se va al carajo ;-)

Una mejora de esto, la publiqué hace muchos años en las news, te pongo aquí las mejoras, que consiste en un pool de threads, por ejemplo, se indexan mantienen solo 5 tablas activas,
y se van creando los indices uno a uno. De esta manera, más coheremente tenemos una indexacion multihilo que no es penalizado por el sistema.
Nosotros lo usamos en el trabajo y va que vuela ;-)

La idea es la siguiente;
/*
Thread Main ( Count MAX by N_THREADS )
|---------> Thhread child table for test.dbf
| |----> child index fname
| |
| |----->child index fcode
|
|---------> Thhread child table for test2.dbf
| |-----> index fname2
|
|---------> N_THREADS
*/

Estoy buscando el código , pero no lo encuentro .
Si interesa busco el nuestro y quito lo que no interesa a nivel interno.

#define N_THREADS 5

STATIC s_num_procesos

Function main()
aDbfs := { .... tus dbf ... }

while nPosTable <= nLen_Table

if ( nTecla := inkey() ) = K_ESC
exit
endif

// No se ha muerto ningun proceso , loop
if N_THREADS = s_num_procesos
loop
endif

cDbf := aDbfs[ nPosTable ]

s_num_procesos++
hb_threadStart( @aCreateIndexe(), cDbf, aNtxs[ nPosTable ],
aKeys[ nPosTable ], aFor[ nPosTable ] )

nPosTable++
end while

hb_threadWaitForAll() // Esperamos a los ultimos.

return


function aCreateIndexe( cFile, aNtx, aExpr, aFor )

... codigo....

hb_mutexLock( s_hMutex )
s_num_procesos--
hb_mutexUnLock( s_hMutex )
return nil

Cuando el hilo muere, se decrementamos el numero de proceso, dando lugar
a que el bucle principal pueda procesar un nuevo hilo.

El problema que tenia es que tenia 5 hilos, y cada uno de ellos pinta en
un lugar de la pantalla, y claro, adivinar donde tiene que pinta era más
complicado que esto
Saludos
Rafa Carmona ( rafa.thefullARROBAgmail.com___quitalineas__)
User avatar
thefull
 
Posts: 729
Joined: Fri Oct 07, 2005 7:42 am
Location: Barcelona

Re: An example of multithreading and Database

Postby cnavarro » Wed Aug 27, 2014 3:30 pm

Rafa, cualquier codigo que compartas me será de gran ayuda
Llevo tiempo queriendo meterme en este tema, pero la informacion encontrada no me era suficiente.
Cristobal Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
El secreto de la felicidad no está en hacer lo que te gusta, sino en que te guste lo que haces
User avatar
cnavarro
 
Posts: 6501
Joined: Wed Feb 15, 2012 8:25 pm
Location: España


Return to FiveWin for Harbour/xHarbour

Who is online

Users browsing this forum: Google [Bot] and 13 guests