oribeiro Posted June 28, 2017 Report Share Posted June 28, 2017 Pessoal, A organização de arquivos (INDEX ON) consome uma quantidade enorme da minha CPU. Tem como tratar isso dentro do programa para evitar o consumo exagerado? Algum desses comandos serve para tratar a forma como o sistema utiliza a CPU? HB_BackGroundActive() Queries and/or changes the activity of a single background task. HB_BackGroundAdd() Adds a new background task. HB_BackGroundDel() Removes a background task from the internal task list. HB_BackGroundReset() Resets the internal counter of background tasks. HB_BackGroundRun() Enforces execution of one or all background tasks. HB_BackGroundTime() Queries or changes the wait interval in milliseconds after which the task is executed. HB_IdleAdd() Adds a background task for being executed during idle states. HB_IdleDel() Removes a task from the list of idle tasks. HB_IdleReset() Resets the internal counter of idle tasks. HB_IdleSleep() Halts idle task processing for a number of seconds. HB_IdleSleepMSec() Queries or changes the default time interval for idle task processing. HB_IdleState() Signals an idle state. SET BACKGROUND TASKS Enables or disables the activity of background tasks. SET BACKGROUNDTICK Defines the processing interval for background tasks. Quote Link to comment Share on other sites More sharing options...
fladimir Posted June 28, 2017 Report Share Posted June 28, 2017 Avaliou se fazendo o INDEX ON com ADDITIVE MEMORY não resolve? Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 28, 2017 Report Share Posted June 28, 2017 Afirmação não procede, reveja sua lógica de indexação. USE CADPAISA NEW EXCLUSIVE ALIAS CADPAISA AEVAL(DIRECTORY( "CADPAISA.cdx" ),{ |aFILE| FERASE(aFILE[F_NAME]) } ) oMeter1:nTotal = RecCount() INDEX ON VAL(Field->FUNCICOD) TAG FUNCICOD TO CADPAISA ; FOR !DELETED() ; EVAL ( oMeter1:Set( RecNo() ), CursorWait(), SysRefresh() ) ; EVERY 10 // NOME DO PAISAGISTA INDEX ON Field->FUNCINOME TAG FUNCIAPELI TO CADPAISA ; FOR !DELETED() ; EVAL ( oMeter1:Set( RecNo() ), CursorWait(), SysRefresh() ) ; EVERY 10 // APELIDO INDEX ON Field->FUNCIAPELI TAG FUNCIAPELI TO CADPAISA ; FOR !DELETED() ; EVAL ( oMeter1:Set( RecNo() ), CursorWait(), SysRefresh() ) ; EVERY 10 Quote Link to comment Share on other sites More sharing options...
oribeiro Posted June 29, 2017 Author Report Share Posted June 29, 2017 Fladimir, O que faz esse ADDITIVE MEMORY ? Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 29, 2017 Report Share Posted June 29, 2017 /* http://forums.fivetechsupport.com/viewtopic.php?f=19&t=28131&start=0 Estaba yo con mis cosas, y repasando la lista de correo de harbour, leí que alguien ponía una función, llamada OrdWildSeek Buscando más información sobre dicha función, me percaté enseguida, que haciendo un poco de malabares y con un indice CUSTOM, y sin apenas esfuerzos, podemos quitar nuestros SET FILTER, que por su utilidad estaban, pero que por su ineficacia no lo usaba prácticamente nadie. Cada vez que he tenido que usar un LIKE en SQL, pasa por mi memoria el SET FILTER ;-) ¿ Y cual es la idea ? El idea es usar un sub-indice a partir del índice activo. ¿ Y como funciona ? Pues a grandes rasgos y para que todo el mundo lo entienda; SET FILTER TO , recurre TODO la DBF en busca de coincidencias. Ah!! y lo bonito que es ver que en el filtro hay solo 2 coincidencias separadas entre si por 200MB, el salto de un registro a otro es de "reír por no llorar" ;-) OrWildSeek, recurre el FICHERO NTX ACTIVO, y nos va diciendo que registro cumple con el patrón que pasamos, y ahí es donde entramos nosotros con nuestro indices CUSTOMS Ahora lo que más nos gusta, el código fuente. Imagina que tenemos una tabla de clientes, y tenemos varios indices, y el 4, la expresión es nombre+apellidos. Ahora, queremos obtener el nombre de SARAH. Pero no solo los que comienzan con SARAH, eso lo podemos solucionar rápidamente con un SCOPE, si no, que forme parte de él, como; ANGIE SARAH LOWE SARAH CARMONA JULIA SARAH SMITH Eso se consigue , pasando el patrón "*"+Cadena+"?" */ cNombre := "SARAH" fast_filter( "*"+ alltrim( cNombre ) + "?", 4, 22, 28 ) Browse() Ahora, ya estaría el filtro activado basado en subindices. /* Sustituto de SET FILTER cExpr Expresion a buscar que forme parte del indice, podemos poner *Texto? , para buscar palabra que forme parte nOrder Sobre que indice activo vamos a recorrer la lista. Por defecto es el indice activo. nRow, nCol Posicion fila,columna para mostrar progreso. Se ejecuta en un hilo aparte Return: Indice anterior */ function fast_filter( cExpr, nOrder, nRow, nCol ) local PantaAnt := savescreen(0,0,MaxRow(),MaxCol()) Local p := hb_threadStart( @Pajaritos(), nRow, nCol ) Local nIndice := OrdNumber() DEFAULT nOrder TO OrdNumber() set order to nOrder INDEX ON &(IndexKey()) TAG _TEMP_ TO tHarbourt ; CUSTOM ADDITIVE MEMORY set order to nOrder go top DO WHILE OrdWildSeek( cExpr, .T. ) OrdKeyAdd( "_TEMP_" ) ENDDO OrdSetFocus( "_TEMP_" ) hb_threadTerminateAll() restscreen(0 ,0 ,MaxRow(), MaxCol(), PantaAnt) return nIndice PROCEDURE Pajaritos( nRow, nCol ) Local pajarito := "|",n := 0 DEFAULT nRow := MaxRow(), nCol := 1 DO WHILE .T. do case case n = 1 pajarito = "|" case n = 2 pajarito = "/" case n = 3 pajarito = "-" case n = 4 pajarito = "\" Otherwise n := 0 end case DispOutAt( nRow, nCol, "Generando Consulta....[ " + pajarito +" ]" ) //, "GR+/N" ) ThreadSleep( 500 ) n++ ENDDO RETURN /* Creo que la función es muy simple y no necesita más explicación, el código habla por si mismo. Lo único es que se crea un hilo para mostrar que se está haciendo alguna cosa. Lo ideal sería que la función OrdWildSeek tuviese un codeblock para hacer llamada e ir mostrando un progreso, pero al no tenerlo, lo he ejecutado en un hilo aparte. He de decir que me sorprende la velocidad, eso si, siempre teniendo en cuenta la cantidad de información a recorrer, avisados estáis. Espero que os guste ;-) */ Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 29, 2017 Report Share Posted June 29, 2017 INDEX ON &(IndexKey()) TAG _TEMP_ TO tHarbourt ; CUSTOM ADDITIVE MEMORY Quote Link to comment Share on other sites More sharing options...
fladimir Posted June 29, 2017 Report Share Posted June 29, 2017 Fladimir, O que faz esse ADDITIVE MEMORY ? Conforme exemplo do João pode ser feitos testes ou modificando sua rotina adicionando no final do INDEX... FOR... (caso tenha for se não independe) ... ADDITIVE MEMORY Faz a criação do índice em memória usando o mínimo de HD, seria um teste pra comparar com a forma atual q vc faz pra ver se incide tb ou não no consumo da CPU, mas adianto q tb acho estranho estar afetando a CPU, pode ser algo indireto q aparenta ser seu programa, exemplo seu programa qdo vai fazer os INDEX faz uma operação em disco q pode ser "interceptada" digamos assim por programas de terceiros como AntiVirus e/ou WARSAW, e/ou Outros e/ou TUDO JUNTO e estar afetando sua aplicação dando a impressão q é algo nela q esta gerando isso mas na verdade são as "porcarias" ops, ferramentas/programas de terceiros q afetam nossos sistemas e outros tb mas como o usuário usa mais nossos sistemas tende a achar q a "culpa" é dos nossos programas... Chove lá em Marte e a culpa é nossa... pra acabar (desculpe ter saido do fio da meada) Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 29, 2017 Report Share Posted June 29, 2017 MEMORY / TEMPORARY Indice na memória -> não tem CDX - recomendado para filtros super rápidos para evitar o uso do SET FILTER(). Modelos de tipos de indices: http://harbour.edu.pl/clipper/es/nge23db.html Quote Link to comment Share on other sites More sharing options...
Theotokos Posted June 29, 2017 Report Share Posted June 29, 2017 Pode ser a chave do INDEX tmb, eu creio.... tipo uma CHAVE muito grande... pode ocorrer este problema... ex:. INDEX ON Nome+Endereco+Bairro+Cidade TAG NEBC To Teste ** Chave compostas Vc esta usando algo assim? Qlq coisa posta ai pedaço da rotina que vc usa para criar os index... Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 29, 2017 Report Share Posted June 29, 2017 Ao entrar em um módulo pesado: use: HB_GCALL( .F. ) E ao sair do seu programa: //--Fecha o Programa Definitivamente FUNCTION TERMINAR() DbUnLockAll() DbCommitAll() DbCloseAll() FreeResources() Release All SysRefresh() HB_GCALL( .T. ) CLEAR MEMORY PostQuitMessage( 0 ) // FECHA O PROGRMA NA MEMORIA __QUIT() RETURN NIL Quote Link to comment Share on other sites More sharing options...
kapiaba Posted June 30, 2017 Report Share Posted June 30, 2017 http://forums.fivetechsupport.com/viewtopic.php?f=3&t=15935&start=0&hilit=setresdebug Quote Link to comment Share on other sites More sharing options...
oribeiro Posted June 30, 2017 Author Report Share Posted June 30, 2017 Vou avaliar e testar todas essas sugestões. Aliás, quantas? Risos Muito obrigado. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.