View Full Version : [JAVA6]oggetto di "dimensione fissa"
Frank1962
10-05-2007, 11:29
Nel java6, che voi sappiate, hanno introdotto "built-in" la possibilità di sapere quanta memoria centrale un oggetto occupa?
Con la java5 utilizzo il metodo descritto in questo (http://www.javaworld.com/javaworld/javaqa/2003-12/02-qa-1226-sizeof.html) articolo ma mi domando, essendo che nella nuova six version ci hanno messo pure un database intero, se si sono ricordati di inserire nelle librerie ufficiali questa funzionalità moolto utile per parecchi programmatori!
Frank1962
10-05-2007, 11:58
ops ....ho notato che il titolo della discussione è un pò ambigua rispetto al corpo del messaggio: per "dimensione fissa" intendo la possibilità che ci sia una qualche collezione (tipo hashmap) che, nella fase di istanziazione, permetta di definire la quantità massima di memoria centrale che la collezione di oggetti occuperà e, nel quel caso si tenti di superare la soglia inserendo un nesimo oggetto, la chiamata del metodo .put generi errore o qualche altro tipo di "paradigma" per notificare l'avvenuto superamento della quantità massima di memoria disponibile.
Puoi usare un agente strumentale (java.lang.instrument). Cosa che avrebbe dovuto fare anche chi ha scritto l'articolo che citi.
Frank1962
10-05-2007, 12:58
Puoi usare un agente strumentale (java.lang.instrument). Cosa che avrebbe dovuto fare anche chi ha scritto l'articolo che citi.
Questa mi è nuova... che so sti agenti "strumentali"? ...ne ho sentito parlare ma per lo più mi sembra che vengano utilizzati per il profiling delle applicazioni.....
Puoi usare un agente strumentale (java.lang.instrument). Cosa che avrebbe dovuto fare anche chi ha scritto l'articolo che citi.
l'articolo è del 2003(e mi sembra che instrument, che fra l'altro nn conoscevo, c'è da java 5
whops. Non so perchè ho pensato subito "guarda questo che non usa gli agenti" senza neanche guardare la data :doh: . Mea grandissima culpa. Domani leggendo un articolo del '98 e penserò "ma guarda questo che non usa Swing!".
Esempio e ci leviamo il pensiero.
Io parto sempre dall'idea "questo è lo strumento che voglio". In questo caso io voglio poter dire:
long dimensioneInByte = SizeAgent.getSizeOf(reference);
La cosa si rivela alquanto semplice. Questo è l'agente strumentale. Una nota: lo chiamo "strumentale" per non usare "di strumentalizzazione" perchè francamente mi fa schifo :D. Ma il termine corretto dovrebbe essere il secondo.
package it.tukano.sizeagent;
import java.lang.instrument.*;
public class SizeAgent {
private static volatile Instrumentation instrumentationInstance;
public static void premain(String args, Instrumentation inst) {
instrumentationInstance = inst;
}
public static long getSizeOf(Object reference) {
return
instrumentationInstance == null || instrumentationInstance == null ?
-1 :
instrumentationInstance.getObjectSize(reference);
}
}
Fine. Per rendere disponibile l'agente si importa il package. Per renderlo "vivo" occorre impacchettarlo in un jar il cui file manifesto avrà la forma:
Manifest-Version: 1.0
Premain-Class: it.tukano.sizeagent.SizeAgent
Con il jar per le mani, si lancia poi il programma che lo usa indicando alla jvm il jar dell'agente:
java -cp .;SizeAgent.jar -javaagent:SizeAgent.jar Main
Occhio però che il "sizeOf" di una mappa è la dimensione dell'oggetto HashMap, non di ciò che contiene. Per fare quello che ti serve dovrai probabilmente creare una mappa i cui metodi aggiungi e rimuovi registrino la dimensione dei nuovi arrivati e dei vecchi in partenza.
whops. Non so perchè ho pensato subito "guarda questo che non usa gli agenti" senza neanche guardare la data :doh: . Mea grandissima culpa. Domani leggendo un articolo del '98 e penserò "ma guarda questo che non usa Swing!".
a maggior sfregio :asd:
http://www.javaworld.com/javaforums/showflat.php?Cat=0&Number=7552&an=0&page=0#Post7552
(come poi dici tu...conta solo le references)
Conta la dimensione dell'oggetto che è poi la dimensione dei suoi campi. Siccome i campi sono puntatori ogni oggetto è relativamente leggero. Penso valga la pena di precisare che il getSizeOf di Instrumentation è il sizeof di C: è fatto con il sizeof di C.
Frank1962
10-05-2007, 15:52
E:\>javac SizeAgent.java
SizeAgent.java:1: package java.lang.instrument does not exist
import java.lang.instrument.*;
^
SizeAgent.java:4: cannot resolve symbol
symbol : class Instrumentation
location: class SizeAgent
private static volatile Instrumentation instrumentationInstance;
^
SizeAgent.java:6: cannot resolve symbol
symbol : class Instrumentation
location: class SizeAgent
public static void premain(String args, Instrumentation inst) {
^
3 errors
E:\>java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
Java HotSpot(TM) Client VM (build 1.6.0-b105, mixed mode)
...ma siamo nella fantascienza!!? :mbe:
Conta la dimensione dell'oggetto che è poi la dimensione dei suoi campi. Siccome i campi sono puntatori ogni oggetto è relativamente leggero. Penso valga la pena di precisare che il getSizeOf di Instrumentation è il sizeof di C: è fatto con il sizeof di C.
per cui in teoria si potrebbe usare lo stesso metodo usato nel link(usare la reflection per procurarsi tutti i riferimenti dell'oggetto ricorsivamente), ma fatto con l'instrument
...ma siamo nella fantascienza!!? :mbe:
Mmmmhhhhh... prova a fare un:
javac -version
xthebol
Probabilmente nel caso di frank creerei un programma a parte che gestisca la struttura dati oppure ripiegherei sulla trasformazione dei dati in forma "binaria", usando quindi un ByteBuffer per contenerli. Nel primo caso somiglierebbe tanto ad un database in memoria, Nel secondo alloco un ByteBuffer di 32 megabyte e quella diventa la mia struttura dati.
Il primo salva la capra, il secondo i cavoli.
La capra è la possibilità di lavorare con degli oggetti. Connetto le due jvm tramite JNI, monitoro la seconda con JMX e sono a posto. Butto un po' di ram per il processo della seconda JVM.
I cavoli sono l'esatto controllo sulla quantità di memoria occupata.
Non so ma penso che tenterei col buffer. Ma dipende anche dai dati.
Leggeti la doc della classe File in java 6, trovi sicuramente novità che ti interesseranno
mhhh... devo essermi perso qualcosa. Che c'è in java.io.File che può esserci utile?
Frank1962
10-05-2007, 23:12
ho creato il file jar e ho inserito il class con il codice compilato postato da pgi, però non riesco a capire come istanziare la classe SizeAgent nel mio progetto, o meglio, non ho capito se questa classe la devo anche inserire insieme alle classi del mio progetto oltre che passarla come file jar al main.....
ps: cmq il problema di compilazione era dovuto, come diceva giustamente pgi, alla versione del javac che era ferma alla 1.4 :D
Includi il jar nel classpath (con -cp in esecuzione e compilazione) e quando vuoi la dimensione di un oggetto blublu semplicemente scrivi:
long size = SizeAgent.getSizeOf(blublu);
Ricordati anche di passare alla JVM l'agente con -javaagent:SizeAgent.jar
Frank1962
11-05-2007, 18:10
String aux = new String("hellooooooooooooooooooo world!!!!");
long dimensioneInByte = SizeAgent.getSizeOf(aux);
sono risucito a farlo funzionare ma a quanto pare il funzionamento risulta non essere dei più intuitivi ....prendendo a esempio una String, come mai se cambio la lunghezza della stringa il output mi viene data sempre dimensione di 24byte (almeno nel mio caso) ? :confused: :confused:
ps: ho il sospetto che sto getSizeOf non fa quello che mi aspettavo....
Tutti i campi di un'istanza di una classe Java sono puntatori.
Se quel puntatore punta ad un array di 40 petabyte comunque conta per 1 puntatore. Perchè "nell'istanza" c'è il puntatore, non c'è l'array.
E' la stessa differenza che c'è tra il sizeof di una struttura c che contiene un array di 100 int ed il sizeof di una struttura c che contiene un puntatore ad int.
Nel primo caso conta il "peso" dei 100 interi, nel secondo il "peso" del puntatore.
Frank1962
11-05-2007, 19:10
Tutti i campi di un'istanza di una classe Java sono puntatori.
Se quel puntatore punta ad un array di 40 petabyte comunque conta per 1 puntatore. Perchè "nell'istanza" c'è il puntatore, non c'è l'array.
E' la stessa differenza che c'è tra il sizeof di una struttura c che contiene un array di 100 int ed il sizeof di una struttura c che contiene un puntatore ad int.
Nel primo caso conta il "peso" dei 100 interi, nel secondo il "peso" del puntatore.
si ma allora che utilità ha un simile metodo? ....cioè alla fine mi ritorna sempre quanto occupa il puntatore; secondo me è poco intuitivo e ambiguo nel nome ....di un metodo SizeObject mi aspetto che venga ritornata la dimensione dell'oggetto che gli passo come argomento, ed è ovvio che un oggetto al suo interno sia composto da altri oggetti (ergo, puntatori a oggetti) :D
Nel caso della String non è possibile calcolare la dimensione del campo che compone l'oggetto stringa istanziato?
E che te la prendi con me? :D Mica l'ho scritto io il linguaggio di programmazione Java :D
Ma tu, di preciso, che ci devi fare con 'sta cosa?
Frank1962
11-05-2007, 19:39
il problema più o meno è questo ......ho un webserver che registra tutte le richieste GET,POST,ecc e le inserisce in un "buffer" in attesa che vengano salvate su database..... questo buffer però dev'essere ovviamente limitato nella dimensione e non superare una certa soglia preimpostata in modo tale che nell'eventualità che ci siano troppe richieste queste non vadino ad occupare tutta la memoria centrale e vengano, anche se non salvate su db, cancellate dal buffer per far posto alle nuove richieste...... spero di essermi spiegato bene (ma temo di no) :D :D :D
Frank1962
11-05-2007, 20:21
premetto, penso sia un'opzione particolarmente utile ...avere la possibilità di creare un contenitore di oggetti "limitato" nell'utilizzo della memoria permette al programmatore di capire quanti oggetti di un certo tipo può istanziare prima che il sistema vada in crisi di memoria centrale ;)
Potresti usare un anello. Una cosa tipo:
public class Ring<T extends Serializable> {
public T push(T value)...
public T extract()..
}
Per realizzare il contratto di Ring crei un buffer di dimensione nota. Al push(value) serializzi value nel buffer. Per extract deserializzi.
Se l'anello è pieno, push restituisce il record rimosso per far posto a value. Se intendi scartare le richieste più vecchie crei un anello LIFO. Altrimenti un FIFO.
A naso, non dovrebbe essere complicato.
Frank1962
11-05-2007, 23:43
si maaaahhh ....un momento!! ...mi stai consigliando di serializzare/deserializzare per l'implementazione? :D :D
Questo che voglio fare è rivolto sopratutto al lato prestazione, cioè il non dover scrivere ogni volta sul db la request del client: se mi consigli di serializzare/deserializzare su buffer mi sa che allora mi conviene direttamente scrivere sul db....
poi non so, magari dalla java 6 la serializzazione è diventata iperveloce.... :sofico:
Devi fare un test per verificare se una soluzione è compatibile con gli obiettivi di performance dell'applicazione che stai sviluppando.
Io ho fatto una prova con questa classe:
package serialtest;
import java.io.*;
public class Query implements Serializable {
private static final long serialVersionUID = 0;
private String path;
private long timestamp;
public Query(String path, long timestamp) {
this.path = path;
this.timestamp = timestamp;
}
public String getPath() {
return path;
}
public long getTimestamp() {
return timestamp;
}
private void writeObject(ObjectOutputStream out) throws IOException {
out.defaultWriteObject();
}
private void readObject(ObjectInputStream in) throws IOException {
try {
in.defaultReadObject();
} catch(ClassNotFoundException ex) {
throw new IOException("Class not found...");
}
}
}
E me la sputa in un ByteArrayOutputStream a poco più di 77.000 istanze al secondo (stringa random di 204 caratteri). Supponiamo che il tempo di deserializzazione sia analogo. Supponiamo inoltre che la macchina di test sia simile a quella di esecuzione.
A questo punto uno deve valutare se 0.013 millisecondi per scrivere e leggere una query con il meccanismo della serializzazione standard siano eccessivi rispetto ad un'altra opzione.
Nota che qui la questione non è se la serializzazione sia o non sia rapida. Anche se impiegasse l'ora e un quarto a cui generalmente si pensa, quest'ora e un quarto andrebbe valutata nel contesto dei requisiti del programma.
Frank1962
12-05-2007, 08:52
i requisti del programma, di solito, sono la massima velocità di esecuzione della query ...nel mio caso essendo il webserver volto a soddisfare le richieste dei client non vorrei, essendoci in mezzo questo salvataggio della richiesta, un eccessivo overhead prima che si passi alla fase di risposta alla GET/POST ....considerando che siamo in un contesto di un webserver che deve gestire parecchi client contemporanemente potrei vedermi crollare le prestazioni proprio per questo eccessivo (forse quasi oserei dire, pedante) salvataggio di tutte le richieste perventure al server.....
Dal tuo codice però non capisco una cosa, la defaultReadObject() legge l'oggetto dallo stream passato come argomento, ma perchè il metodo non ritorna l'oggetto appena deserializzato? :confused:
ps: ma i 0.013s li hai messi a caso? ...perchè considerando le 77000 istanze al secondo e ponendo il tempo di deserializzazione equivalente a quello di serializzazione abbiamo 1s/(77000/2) che è mooolto più basso di 13ms....
ps: ma i 0.013s li hai messi a caso?
Be', no. Ho scritto "millisecondi" e non "secondi".
Invece è ambiguo quando scrivo
...se 0.013 millisecondi per scrivere e leggere...
Qui intendevo "...se 0.013 millisecondi per scrivere e 0.013 millisecondi per leggere..."
Per questo ho detto 0.013 e non 0.026.
Il meccanismo tramite cui è realizzata la (de)serializzazione standard non restituisce l'oggetto deserializzato ma, in un certo senso, "riempie un'istanza vuota". Tale istanza è poi usata come valore restituito dal metodo readObject() di ObjectInput.
Frank1962
12-05-2007, 11:53
Be', no. Ho scritto "millisecondi" e non "secondi".
opss ...una piccola svista :D
in effetti, però, non sapevo che un elaboratore avesse una precisione dell'ordine del milionesimo di secondo!
Interessante la possibilità di serializzare/deserializzare un oggetto in quel modo ...ma l'ObjectInputStream e l'ObjectOutputStream fanno le veci del "database" in memoria? ..cioè se vado a serializzare più oggetti dello stesso tipo in quegli stream il distinguo nell'andarli a deserializzare viene eseguito automaticamente? a prima vista da come hai scritto il codice sembrerebbe proprio di si
Non so se il comune hardware offra una precisione al milionesimo di secondo. So che il timer che Java usa per nanoTime() ha una granularità massima di 1 millisecondo. Io ho fatto un test su 50000 serializzazioni e ho diviso il tempo totale per il numero di istanza serializzate, ottenendo il valore medio che ho indicato.
Quanto alla distinzione automatica se intendo correttamente il dubbio la risposta è sì. Cioè se scrivo 3 oggetti distinti posso poi leggere distintamente questi stessi 3 oggetti.
Frank1962
12-05-2007, 12:27
Quanto alla distinzione automatica se intendo correttamente il dubbio la risposta è sì. Cioè se scrivo 3 oggetti distinti posso poi leggere distintamente questi stessi 3 oggetti.
ma quindi questo vuol dire che l'ObjectInputStream deve essere in qualche modo "collegato" all'ObjectOutputStream ...cioè dove scrivo poi e dove dovrò andare a leggere, o sbaglio? ...e in questo caso come faccio a collegate un outputstream a un inputstream che si appoggiano a un bytearrayinputstream/outputstream?
oltretutto, come mai i metodi write/readObject della classe Query sono private?
Mhhh... :eh:
Hai presente quando scrivi un testo su un file? Ecco, se vuoi avere indietro quel testo devi leggere lo stesso file.
Se il testo è "pippo" e sul file scrivo prima la p, poi la i, poi la p eccetera, per leggerlo io devo leggere prima la p, poi la i, poi la p eccetera.
Questo è il collegamento che deve sussistere anche tra ObjectOutput e ObjectInput.
Quanto all'output-input che si collega al byte array... la metti giù un po' troppo complicata.
Tu serializzi l'oggetto in memoria e lo deserializzi leggendo dei byte dalla regione di memoria in cui li hai scritti.
I metodi readObject e writeObject sono private perchè chi ha progettato il meccanismo della serializzazione standard ha voluto esprimere il vincolo "non invocate direttamente questi metodi, grazie".
Frank1962
12-05-2007, 13:19
Mhhh... :eh:
Se il testo è "pippo" e sul file scrivo prima la p, poi la i, poi la p eccetera, per leggerlo io devo leggere prima la p, poi la i, poi la p eccetera.
suppongo che intendi l'accesso in modalità fifo? .....io pensavo invece che, dato un oggetto serializzabile, passandogli a un metodo xyz uno stream lui vi si serializzasse e si occupasse di recuperare tutte le informazioni necessarie in un secondo momento alla chiamata di un determinato metodo zyx.
Con la modalità fifo sono invece obbligato a leggermi tutti gli oggetti serializzati prima di ottenere quello voluto! :(
Query q1 = new Query("ciao",1234567890);
Query q2 = new Query("hello",1234567890);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try {
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(q1);
oos.writeObject(q2);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
q1 = (Query)ois.readObject();
q2 = (Query)ois.readObject();
System.out.println(q2.getPath());
} catch (Exception e) {
e.printStackTrace();
}
...e se volessi deserializzare q2 senza serializzarmi q1?
a me piacerebbe invece fare un'utopia simile (:D) :
Query q1 = new Query("ciao",1234567890);
Query q2 = new Query("hello",1234567890);
DatabaseInMemoriaCentraleConUnNomeTroppoLungo dbmem = new DatabaseInMemoriaCentraleConUnNomeTroppoLungo(10YottaByte);
q1.miserializzo(dbmem);
q2.miserializzo(dbmem);
Query q1= q1.mideserializzo(dbmem);
System.out.println(q1.stampalostampabile());
Se devi creare un buffer per un servizio che evade delle richieste avrai una politica di ordinamento delle evasioni che si riflette nell'accodamento delle richieste. Se la politica di evasione richiede un accesso casuale, tu crei un buffer ad accesso casuale. Se è richiesto un accesso lifo, crei un buffer lifo. Se è richiesto un accesso fifo, crei un buffer fifo.
Se il server evade le richieste un po' come gli gira e un po' come tira il vento allora non è più un problema di programmazione. Può essere poesia o pittura o una qualsiasi altra nobilissima e affascinante attività creativa dell'uomo. Ma non è programmazione.
La serializzazione si occupa di trasformare un oggetto in un pacchetto di byte e la deserializzazione di trasformare un pacchetto di byte in un oggetto.
Le specifiche del programma che devi creare le conosci tu e tu devi decidere se la serializzazione sia o non sia idonea a rappresentare la soluzione ad uno dei problemi che hai già risolto.
E' possibile che io mi sbagli, perchè si tratta pur sempre di una conversazione astratta su questioni delineate a botta e risposta su un forum, ma ho l'impressione che tu abbia il problema ma non la sua soluzione.
La programmazione è l'attività di rappresentazione della soluzione ad un problema. Non è un tecnica di soluzione di problemi.
Devi già sapere quello che devi fare. Poi prendi gli strumenti offerti dalla piattaforma di programmazione che hai scelto e li usi per rappresentare, per tradurre quello che già sai di dover fare.
Io ti parlo di serializzazione perchè la soluzione che ho trovato al problema che hai proposto è rappresentabile con questo strumento. Pensavo che la mia soluzione coincidesse con la tua ma ora mi viene il dubbio che, nel nostro dialogo, la mia soluzione sia anche l'unica in ballo :eek:
Frank1962
12-05-2007, 14:58
ammetto che forse la strada al "contratto" che la discussione originariamente voleva condurci si è andata un pò a perdere :D ...ma in realtà il problema è sempre stato quello: capire quanto un oggetto o una collezione di oggetti occupa in memoria centrale.
Se la serializzazione in un bytearrayoutputstream mi permette di far ciò: ben venga! ;)
Il problema è che non vorrei che questa soluzione mi portasse fuoristrada sotto due aspetti: lato prestazione e lato "usabilità" di quello che voglio creare.
Se dal lato prestazioni abbiamo visto che ciò conviene dal lato usabilità rimango con qualche perplessità; ovvero: se voglio recupare l'oggetto di indice i dalla sfilza di oggetti che inserisco nel mio dbase come cavolaccio faccio se non applico qualche paradigma in chiave poetica/pittorica di influenza ermetista ....o per meglio intenderci ( :D ) ogni volta che serializzo UN oggetto devo prendere il singolo byte[] contenente i byte dell'oggetto e inserirlo in una hashmap per riuscire a creare una sorta di accesso indicizzato?
Il dubbio/perplessità/confusione veniva dal fatto che pensavo la serializzazione avese bultin la possibilità di fare il distinguo (tramite un suo protocollo) degli oggetti serializzati all'interno di un'area di memoria (in questo caso il nostro bytearrayoutputstream).
Frank1962
13-05-2007, 00:19
ecco una prima implementazione ....a voi il giudizio!! (sopratutto per pgi, essendo ormai nato un "contenzioso" tra un nobilissimo programmatore java (pgi) e un lurker con un attacco mistico di posting (frank) :D )
import java.io.*;
import java.util.HashMap;
public class ObjectDBase {
private int mode = 0;
private int total = 0;
private int maxsize = 0;
private Queue q = new Queue();
private HashMap<Integer,Object> hm = null;
private ByteArrayOutputStream baos = null;
private ObjectOutputStream oos = null;
ObjectDBase(int maxsize, int mode) {
this.mode = mode;
this.maxsize = maxsize;
hm = new HashMap<Integer,Object>();
try {
baos = new ByteArrayOutputStream();
oos = new ObjectOutputStream(baos);
} catch (IOException e) {
e.printStackTrace();
}
}
public void addObject(int key, Object o) throws Exception {
baos.reset();
oos.reset();
oos.writeObject(o);
byte[] aux = baos.toByteArray();
if(!(total+aux.length>maxsize)) {
insertObject(key, aux);
} else {
if(mode==0 || aux.length>maxsize) {
throw new Exception("spazio insufficente");
} else {
while(total+aux.length>maxsize) {
Integer inx = (Integer)q.deQueue();
byte[] a = (byte[])hm.get(inx.intValue());
total -= a.length;
hm.remove(inx);
}
insertObject(key, aux);
}
}
}
private void insertObject(int key, byte[] array) {
hm.put(key, array);
q.enQueue(key);
total += array.length;
System.out.println(total);
}
public Object getObject(int key) {
byte[] aux = (byte[])hm.get(key);
ByteArrayInputStream bais = new ByteArrayInputStream(aux);
try {
ObjectInputStream ois = new ObjectInputStream(bais);
return ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
}
il main per testarla:
public static void main(String... args) {
try {
int i = 0;
while(true) {
i++;
odb.addObject(i, buildmap());
}
} catch (Exception e1) {
e1.printStackTrace();
}
public Map buildmap() {
HashMap map = new HashMap();
int i = 0;
while(i<(int)100.0*Math.random()) {
map.put(i, Math.random());
i++;
}
return map;
}
}
dove Queue è un'implementazione di una semplicissima collezione in modalità fifo ....la utilizzo per ricordarmi quali sono state le prima chiavi inserite in modo tale sa sapere quali oggetti dovrò rimuovere dall'hashmap nell'eventualità che lo spazio si esaurisca.
Mi sorge un problema sul fatto della compressione dei dati ...ho provato a utilizzare il normale deflater fornito dalle librerie java ma ho notato che la dimensione dei dati compressi molte volte tende a superare la dimensione dei dati originali (per piccole quantità di dati, dell'ordine di una stringa di 200/300 caratteri) quindi mi chiedo se ci può essere qualche alternativa che non vadi a salvare ogni volta il dizionario nei dati di compressione.
Ma che nobiltà, eleganza e via sproloquiando. I fatti, contano i fatti! Carta canta! :D.
A vederlo direi che funzioni. La mappa puoi dichiararla come <Integer, byte[]>, a meno che i valori non debbano effettivamente essere Object o figli. Mi sfugge la ragione per cui devi avere una mappa ma tra noi due sei senz'altro tu a sapere come dev'essere fatto 'sto programma.
Frank1962
13-05-2007, 12:38
A vederlo direi che funzioni. La mappa puoi dichiararla come <Integer, byte[]>, a meno che i valori non debbano effettivamente essere Object o figli. Mi sfugge la ragione per cui devi avere una mappa ma tra noi due sei senz'altro tu a sapere come dev'essere fatto 'sto programma.
si potrei metterci anche un byte[] come tipo ....utilizzo l'hashmap per poter dar la possibilità a chi utilizza questa classe di poter associare un identificativo all'oggetto che vuole salvare nel dbmen: hai qualche alternativa? dici che con una List posso ottenere lo stesso risultato?
Sul discorso "compressione" non mi dici nulla? :D
Mi intendo di compressione come di scissione dell'atomo. So che le librerie standard fornisco compressori/decompressori zlib, zip o gzip e qui mi fermo.
Frank1962
13-05-2007, 13:34
Mi intendo di compressione come di scissione dell'atomo. So che le librerie standard fornisco compressori/decompressori zlib, zip o gzip e qui mi fermo.
non sei esperto di scissione dell'atomo? ...è gravissimo per un programmatore di java avere simili lacune!! :D :D
cmq come da documentazione java della classe deflater:
setDictionary
public void setDictionary(byte[] b,int off,int len)
Sets preset dictionary for compression. A preset dictionary is used when the history buffer can be predetermined. When the data is later uncompressed with Inflater.inflate(), Inflater.getAdler() can be called in order to get the Adler-32 value of the dictionary required for decompression.
Parameters:
b - the dictionary data bytes
off - the start offset of the data
len - the length of the data
See Also:
Inflater.inflate(byte[], int, int), Inflater.getAdler()
l'idea penso sia quella di fornirgli un dizionario fissato in modo tale che lavori su quello e non vadi a crearsene ogni volta una suo andandolo a salvare insieme ai dati compressi.... ma perchè cavolaccio non mi dicono COME cavolo si crea quell'array da passare come argomento!! :(
Frank1962
13-05-2007, 14:05
cmq togliendo il problema della compressione che, da post su forum.java.sun.com (trovato dopo un casino di tempo, dato che google sembri disprezzare tale forum) il problema sembra di rapida soluzione, volevo domandarti che cosa non ti è chiaro della mia classe dopo che ho postato il codice, dalle tue parole infatti:
Mi sfugge la ragione per cui devi avere una mappa ma tra noi due sei senz'altro tu a sapere come dev'essere fatto 'sto programma.
...sembra che non riesci a trovare, se mai ci fosse, la ragione per cui un "qualcuno" dovesse implementare "sta cosa"! :D
Cioè, la necessità di avere un "contenitore" di oggetti limitato superiormente penso non sia cosa di poco conto come soluzione di parecchie problematiche tra i programmatori java...... o sbaglio?
Come no. Figurati che se non devo fare un contenitore di oggetti limitato superiormente io la mattina neanche mi alzo. :D
Tu devi fare quello che pensia sia corretto per il tuo programma. A me sembra strano che ti serva una mappa perchè, probabilmente, mi sono fatto un'idea del programma che è diversa da quello reale.
Il programma che mi sono immaginato è questo.
C'è un server che mastica richieste. Le richieste provengono da un numero non determinato di client.
Il server ha una limitata capacità di evasione delle richieste.
Tra il server e i client infili un buffer tampone. Il buffer accumula le richieste provenienti dai client e il server le consuma in ordine di arrivo.
Il buffer ha una dimensione prefissata. Quando il buffer si riempie, possono succedere tre cose (sempre nella mia idea del programma)
1. il buffer rifiuta le nuove richieste
2. il buffer rimpiazza la richiesta più vecchia con la richiesta più recente
3. il buffer mette i client in attesa
E qui la mappa non ci sta. La mappa permette di prelevare una richiesta in particolare. Non serve per prelevare la richiesta più vecchia o la più recente, perchè questo compito lo assolve già la coda del buffer. La mappa offre un criterio di "scelta" diverso. Qual'è questo criterio? Perchè il server dovrebbe prelevare (presumo per evadere) una richiesta senza rispettare l'ordine di arrivo? Forse alcune richieste sono prioritarie? Ma in questo caso la priorità dovrebbe essere gestita nell'accodamento delle richieste.
Ecco, sono perplessità di questo tipo che mi fanno apparire strana quella mappa. Ma questo non vuol dire che sia stramba. Insomma, se l'hai messa una ragione ci sarà. Io mi fido.
Frank1962
13-05-2007, 14:48
Ecco come temevo....il parlare di webserver e prestazioni non ha aiutato nell'esporre la mia idea! :(
Il problema è nel salvataggio delle richieste e non nel soddisfacimento; per meglio intenderci faccio un piccolo schemino:
1) arriva una richiesta GET xyz
2) devo salvarla da qualche parte
3) chiamo il metodo sodisfy(request)
il punto 2) è una cosa in più, cioè non comprometterebbe il funzionamento del webserver ....serve solo a registrare le richieste pervenute al server; quello che sto cercando di fare è, non di creare un buffer, bensì qualche cosa che assomigli di più a una cache, una cache che sia il più trasparente e meno invasiva (in termini di cputime e memoria) possibile, che permetta di salvare istanze di oggetti in maniera flessibile a seconda delle esigenze occupandosi anche dell'eventualità che il processo voglia salvare "troppi" oggetti, un qualche cosa che permetta al flusso di controllo del programma di passare il più velocemente dalla fase 1 alla fase 2 ;)
Adesso mi fai venire in mente un logger, solo che un logger normalmente non ha una controparte nella memoria volatile a meno che non sia un "RAM" DataBase (nome che mi sono inventato io adesso).
Se fosse un logger allora quando arriva la richiesta la passeresti prima alla coda del logger e poi la rifileresti al server.
Il passaggio alla coda si risolve in un'accodamento concorrente. Qui il tempo di attesa è quello eventualmente necessario affinchè il Thread che consuma la coda di logging estragga l'elemento (credo sia nell'ordine del millisecondo o meno) se l'offerta si sovrappone all'estrazione.
Non ti nasconderò, tuttavia, che neppure qui ci vedo la mappa. Dici che è ora che io mi faccia controllare le cataratte? :D
^TiGeRShArK^
13-05-2007, 17:24
:mbe:
io ho capito che deve cachare gli oggetti che vengono inviati al server web tramite una get..
ma..
ammesso che ho capito bene...
perchè reinventare la ruota?
solitamente i web server non hanno già meccanismi di caching che possono essere configurati a piacere? :mbe:
la risposta ovvia è: Non ho capito un kazz del problema...
ma questo è molto probabile :D
Frank1962
13-05-2007, 22:18
:mbe:
solitamente i web server non hanno già meccanismi di caching che possono essere configurati a piacere? :mbe:
...non penso che i sistemi di caching implementati nei webserver permettano di comprimere in memoria i dati in attesa di essere scritti su logfile ;)
e poi se uno vuol fare un webserver in java come fa a usare quelle "ruote già inventate" in apache o similari? :D
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.