Newsgroup: it.comp.lang.delphi
Titolo: Tempo rimanente

Ciao a tutti,
   da un file di testo devo importare circa 1200000 record.
La procedura e' abbastanza lunga, cosi' avevo intenzione di visualizzare il 
tempo rimanente per finire il processo.
 
Il problema e' il come farlo, non ho la minima idea .....
Pensavo di usare il gettickcount e di metterlo nella procedura di 
importazione.
La logica e':
- Prendo il tempo prima di fare il parsing della riga del file con 
gettickcount
- prendo il tempo alla fine del parsing e del salvataggio del record con 
gettickcount
- calcolo il tempo utilizzato con la differenza dei due tickcount
- lo moltiplico per i restanti record
- converto i millisecondi in minuti;secondi e lo visualizzo !
 
Puo' funzionare ??
 
Grazie per l'attenzione
 
Ciao
 
Daniele 
 

 Puo' funzionare ??
 
La stima rischia di essere molto rumorosa a causa della granularit�
di gettickcount (es 0ms, 15ms, 30ms...).
 
Io farei passare 5, 10 secondi ed andrei a contare quanti record
sono stati processati e poi farei il calcolo sul tempo restante.
Se ad esempio processi 100 record al secondo, uno ogni 10ms,
con gettickcount rischi di fare misure che ballano tra 0ms e
15ms (dipende dal sistema operativo e dal clock della maccchina)
e la stima sul tempo totale varierebbe tra 0 e 5 minuti, sballati
entrambi.
 
Se campioni i record ogni 5 secondi leggerai 499, 500 o 501 record
con un errore inferiore all' 1% sulla stima totale.
 
Ciao,
 
-- 
Virgilio Lattanzi        Teamsystem Communication srl
Tel: 
+39 0733 818863
     via Fontanella, 38
Fax: 
+39 0733 819133
     62012 Civitanova Marche MC
WWW: 
www.tscomm.it
       ITALY

 Civitanova Marche MC
Tho, lunedi' sono a Macerata .... quasi quasi se non mi prendono tutto il 
tempo passo a suonarti il campanello !! 
 

 con un errore inferiore all' 1% sulla stima totale.
 
Oppure puoi campionare ogni tot record invece che ogni tot secondi.
 
ciao
Giacomo
 
 
 

 Oppure puoi campionare ogni tot record invece che ogni tot secondi.
 
S�, lo sviluppatore strafigo dovrebbe ragionare in termini di
probabilit� d'errore. Non conoscendo a priori il tempo di processamento
della singola unit�, bisognerebbe misurare sia quanti record nell'unit�
di tempo (eg. 1s), sia quanto tempo � necessario per l'unit�
complessiva di record (eg. 100 record).
Poi scegliere al volo quale parametro usare.
 
Se ad esempio in un secondo misurassi 10 record, l'estrapolazione mi
porterebbe ad un errore dell'ordine del 10%, per cui mi converrebbe
aspettare di contare 100 record e misurarne il tempo relativo.
 
Se invece il processamento fosse molto rapido, 100 record li processerei
ad es. in 30 ms che sono vicini alla granularit� con cui misuro il
tempo, per cui mi converrebbe fare la misura opposta, cio� quanti
record in un secondo.
 
Tutto questo se non ho nulla da fare, perch� anche una bella
clessidra senza stime sul tempo rimanente fa la sua porca figura. :)


 il tempo rimanente per finire il processo.
Se non vuoi impazzire e farti pippe mentali c'� la strada canonica di
fare una progress bar.
Lascia all'utente la possibilit� di inferire il tempo restando in
funzione di quanto va veloce la progressbar.
Per fare questa semplice implementazione:
prendi il numero totale dei record e impostali come valore massimo della
progressbar.
Per ogni record che elabori incrementa la progress di 1.
 
fine dei problemi.
 
 
-- 
morde
Android
QT 4.7
Delphi (5,6,7.. expired)
Firebird Database
 

 Per ogni record che elabori incrementa la progress di 1.
 
Facendo cosi hai un impatto devastante sulle performance dell'operazione.
Meglio farlo ogni "n" records,  dove n e' calcolato in funzione del numero totale di records. Ad esempio:
 
...
  n := 10;
  if NumeroMaxRecord > 5000 then begin
    n := NumeroMaxRecord/1000
  end;
  if n > 500 then begin
    n := 500;
  end;
 
  progressbar.Max := NumeroMaxRecord;
  progressbar.Position := 0;
  StepCount := 0;
 
Poi, nel loop che processa i record:
 
  ... 
  inc(StepCount);
  if (StepCount = n) then begin
    progressbar.Position := Progressbar.position + n;
    progressbar.Repaint; // O IN ALTERNATIVA: APPLICATION.PROCESSMESSAGE;
    StepCount := 0;
  end;
  ...
 
La scelta tra repaint o processmessage dipende da te.
La prima fa solo il repaint della progressbar lasciando alla buona volonta del sistema operativo la decisione di processare gli eventi in coda.
In questo modo rischi un freeze, cosa che personalmente detesto.
 
Se usi processmessage non hai il freeze e sei TU a decidere quando il sistema deve processare gli eventi in coda, e l'utente, se pur piu' lentamente, intanto puo' usare il pc per fare altro.
 
 
A parte cio, la ovvia (ma non per tutti) domanda:
deve PER FORZA essere un operazione eseguita dall'utente a sua discrezione o potrebbe essere un batch pianificato che gira in un tempo morto?
 
 
A.

 o potrebbe essere un batch pianificato che gira in un tempo morto?
 
Sebbene sia implementata un funzione di update giornaliera (decisamente piu' 
snella), non so quando chi usa il programma potrebbe fare un'importazione 
totale.
Va anche tenuto presente che, sulla stessa macchina, per esportare dal DB 
(il solito db cobol) al file di testo il processo richiede la belleza di 
20-30 minuti !!!!
 
Grazie ancora a tutti
 
Ciao
 
Daniele
 

 (il solito db cobol) al file di testo il processo richiede 20-30 minuti !!!! 
il "processo" cosa e'? Fatto da CHI usando COSA?  
E' un export stupido o fa elaborazioni, trasformazioni, consolidamenti etc?
 
 
A.

 etc?
Bho, chi lo sa  .....
Ovviamente l'esportazione la fa un operatore (a loro dire) una volta alla 
settimana per l'adeguamento prezzi.
Quello che ho potuto vedere e' che nella querry di esportazione (e' chiamata 
cosi' nel programma) fa vedere i campi del record e permette l'esportazione 
dal mega db secondo i criteri impostati.
Sempre dal programma l'esportazione avviene selezionando i campi
Codice
EAN
Descrizione
IVA=22
 
alla fine dell'elaborazione (20 minuti in cui non so che operazioni fa) 
genera una griglia dalla quale e' possibile salvare un file di testo (altri 
5-6 minuti).
 
Ovviamente da quel lato non importa granche, l'importante e' migliorare il 
mio lato !!!!
 
E' sempre un piacere avere i tuoi validi suggerimenti
 
Ciao
 
Daniele
 
 

 dal mega db secondo i criteri impostati.
 
ok. Per curiosita, che sistema e'? 
 
A.

dovrebbe stare in una classe che espone una callback da invocare ogni n
righe:
 
Faccio seguito alla tua giusta osservazione sull'impatto che la
progressbar ha sulle performances.
A questo proposito, si dovrebbe poter rimediare mettendo la progressbar
in un thread apposito liberando cos� il thread principale dell'applicazione.
C'� pi� lavoro da fare ma in questo caso la progressbar diventerebbe
asincrona rispetto al main thread impedendo cos� di saturare l'events loop.


 ok. Per curiosita, che sistema e'?
Gestionale per farmacie, ha molti nomi a seconda del distributore .... mi 
spiego e' un programma scritto interamente in cobol e usa per la parte db 
una tecnologia (non vorrei dire assurdita') detta file system. In teoria 
ogni distributore (1 o 2 per regione) ha la possibilita' di personalizzarlo 
con degli add on anche loro in cobol.
Uno dei nomi piu' diffusi e' copernico.
 
Buon Natale a tutti
 
ciao
 
Daniele 
 

 mi spiego e' un programma scritto interamente in cobol
 
Adoro sentir ancora parlare del cobol.. AMLO sta gi� ridendo sotto i
baffi.. :)


 in un thread apposito liberando cosï¿½ il thread principale dell'applicazione.
 
..e poi devi usare un sincrhonize...
La VCL va solo sul main thread, e a detta di Cantu' acneh FM2.
 
A.

nel 1998 ho usato la banca dati di federfarma.
Stavo lavorando ad un sw per le farmacie.
Ricordo ancora la quantita' di codici esistenti per ogni singolo farmaco...
 
A.

 in un thread apposito liberando cosï¿½ il thread principale dell'applicazione.
 
Io farei il contrario: metterei in un thread separato la procedura di importazione, creando un discendente di *TThread* e mettendo un campo che viene valorizzato con il numero totale dei record e quello del record attualmente in elaborazione per poter visualizzare il suo progresso.
 
Per il monitoraggio del progresso, metterei un semplice *TTimer* nel Form che ogni X milisecondi vada a recuperare da questo thread lo stato del progresso e lo mostri nella *TProgressBar*.
 
In questo modo, la procedura di importazione nel thread esterno ha tutta la CPU di cui può disporre, nel senso che non deve occuparsi di chiamare/sincronizzare/segnalare la variazione del proprio stato, mentre il thread principale dell'applicazione riceve solo ogni tanto (in base al valore dell'Interval) un "tick" per andare ad allineare la ProgressBar con lo stato attuale dell'elaborazione, senza essere troppo invasivo e mantenendo i due "mondi" separati.
 
Con un pulsante si potrebbe pure intervenire sul thread per terminarlo, nel caso si voglia supportare l'interruzione/annullamento del processo di importazione.
 
Ciao!
  Marco.
 
-- 
MARCO BREVEGLIERI
#Home: 
http://www.marco.breveglieri.name
 
#Blog: 
http://www.compilaquindiva.net