Posted by Dibi Store
Sat, 28 Jun 2008 05:42:00 GMT
Ruby è un linguaggio naturale, ma non per questo semplice, infatti offre una sintassi molto ricca e articolata. Oggi volevo parlare di due generatori non molto usati (ma non per questo inutili) che possono offrire dei grandi vantaggi al programmatore.
Fiber
Fiber è una nuova classe introdotta in ruby 1.9 che permette di effettuare delle chiamate sequenziali ad un oggetto fiber.
Continuation
La classe Continuation è già presente in Ruby 1.8, tuttavià verrà rimossa dalla prossima release, in quanto non è portabile tra le diverse versioni. Di fatto ne viene sconsigliato l'utilizzo, e se ne incoraggia quello della classe Fiber (che fa un lavoro simile).
Approfondimenti
The Ruby programming language (link non sponsorizzato).
no comments | no trackbacks
Posted by Dibi Store
Fri, 20 Jun 2008 05:39:00 GMT
Se siete alla ricerca di un elenco completo di consigli per lavorare da casa,questo articolo in lingua inglese potrebbe interessarvi.
Posted in metodologie | Tags produttivita | no comments | no trackbacks
Posted by Dibi Store
Wed, 04 Jun 2008 20:49:00 GMT
There’s
the old story of the young project manager, where his senior
programmer announced she was pregnant and going to leave
the project, and he protested that this “wasn’t on the project
plan.”
Posted in metodologie | no comments | no trackbacks
Posted by Dibi Store
Mon, 26 May 2008 05:38:00 GMT
Passenger è un modulo apache sviluppato di recente da phusion che permette il deploy di applicazioni rails anche in grande scala.
La cosa interessante è che questa soluzione sta già diventando la de-facto per una buona parte di sviluppatori rails. Avrò occasione di provare questo prodotto al più presto, e quindi di darvi maggiori info e feedback, nel frattempo vi lascio alcuni link utili per iniziare a darci un occhiata.
modrails.com: sito ufficiale.
28 mod_rails / Passenger Resources To Help You Deploy Rails Applications Faster: link utili per iniziare da subito.
Ask Your Doctor About mod_rails: interessante articolo scritto da Geoffrey Grosenbach.
Posted in ruby on rails | Tags deploy, passenger | no comments | no trackbacks
Posted by Dibi Store
Sat, 24 May 2008 09:01:00 GMT
Readline è una libreria che vi permette di usare alcune interessanti funzioni da shell, come ^R per la reverse search oppure il supporto ai caratteri accentati. Sarebbe utile poter usare questo supporto anche all'interno di irb, tuttavia nella versione per mac osx non ci viene permesso. Tuttavia, questo articolo ci spiega come abilitare la libreria in meno di 5 minuti.
Posted in ruby | Tags irb | no comments | no trackbacks
Posted by Dibi Store
Sun, 18 May 2008 09:32:00 GMT
E' notizia di ieri sera che rubinius è finalmente in grado di eseguire applicazioni rails. Entro la fine dell'anno, come detto da Fowler, saremo in grado di assistere al deploy di applicazioni commerciali su questa piattaforma.
Posted in ruby | Tags rubinius | no comments | no trackbacks
Posted by Dibi Store
Wed, 07 May 2008 13:12:00 GMT
Il modello sostitutivo, in ambito informatico, è il più semplice di una serie incrementale di modelli che descrivono come un interprete analizza il programma. L'uso del modello sostitutivo è quotidianamente usato anche dagli utenti per capire come una determinata procedura funziona.
Per cogliere al volo il concetto analizziamo il seguente listato:
pi: 3.14159
circonferenza(x): x * x * pi
somma_di_circonferenze(x, y): circonferenza(x) + circonferenza(y)
somma_di_circonferenze(4, 7) = ?
Read more...
Posted in programmazione | no comments | no trackbacks
Posted by Dibi Store
Sat, 29 Mar 2008 22:11:00 GMT
Quando programmiamo in alcuni linguaggi di alto livello, come ad esempio in ruby, non abbiamo bisogno di preoccuparci di come viene gestita la memoria da parte del computer. Tuttavia è interessante (oltre che utile) conoscere almeno a livello superficiale cosa avviene dietro le quinte. Questo articolo ha l'obiettivo di descrivere in maniera generale il processo di lettura e scrittura della memoria.
Registri
I registri sono la parte più performante della memoria, ma sono anche molto costosi, infatti nei processori 80x86, abbiamo a disposizione solo 8 registri da 32 bit (più altri di minore capacità). Quando lavoriamo a basso livello ci conviene sempre utilizzare i registri (se possibile) in modo di sfruttare appieno la velocità della nostra cpu.
Cache
La cache è quella parte della memoria che memorizza i valori corrispondenti a diversi indirizzi fisici di memoria. In ogni computer può esser presente uno o più livelli di cache, ad esempio L1 e L2. Prendendo come esempio L1, esso è costituito da diverse cache lines (linee di cache) che a loro volta contengono delle sequenze di byte.
In che modo vengono memorizzati i dati in cache?
Solitamente vengono usate tre strategie per determinare in quale cache line inserire il valore presente in memoria:
- strategia a mappatura diretta: da ogni indirizzo di memoria viene ricavata la relativa linea di cache attraverso un algoritmo. Tuttavia essendo le linee di cache un numero molto inferiore rispetto agli indirizzi di memoria, è probabile che si creino dei conflitti qualora si tenti di sovrascrivere una linea di cache già usata in precedenza.
- strategia a mappatura associativa: in questo caso il controller di cache, ha la possibilità di decidere arbitrariamente quale linea di cache utilizzare. Questo metodo è poco usato in quanto molto dispendioso a livelli di performance.
- memoria associativa n-volte (n-way set associative cache): In questo caso il blocco di cache che abbiamo a disposizione viene suddiviso n volte (per esempio 2 o 4), e queste suddivisioni vengono chiamate set. Questo ci permette di usare la strategia a mappatura diretta direttamente sui set, mentre al loro interno possiamo usare la strategia a mappatura associativa.
E quando tentiamo di sovrascrivere una linea di cache utilizzata in precedenza?
Nel caso in cui tentiamo di sovrascrivere una porzione di memoria attraverso una mappatura diretta, viene semplicemente dovrascritta la parte interessata, mentre nel caso stiamo usando una mappatura associativa, il discorso diventa più complesso: in alcuni casi viene sostituita la linea di cache usata meno recentemente, mentre altre volte la sostituzione avviene in modo randomico oppure attraverso il meccanismo fifo (first in first out).
Cosa succede quando scriviamo dati in memoria principale?
Ma soprattutto: quando tento di salvare un dato in un indirizzo di memoria, il livello di cache che si occupa di memorizzare il valore, come interagisce con questo processo?
Anche qui le scelte più usate sono due:
- write through policy
- write back policy
Write through policy; ogni volta che memorizziamo un dato in memoria, dapprima viene salvato in cache, subito dopo nella memoria principale. Write back policy invece salva prima il dato in memoria, e dopo un certo lasso di tempo lo salva nella memoria principale. Qualora stiamo salvando grosse quantità di memoria, nel primo caso il BUS che trasporta i dati dalla cache alla memoria principale finisce per intasarsi, analogamente nel secondo caso se tentiamo di memorizzare un dato nella stessa linea di cache, dobbiamo attendere che venga trasferito il rispettivo valore nella memoria principale. Nel caso la performance sia un elemento essenziale, è compito del programmatore (nei limiti del possibile) assicurarsi di utilizzare la cache in maniera propria.
NUMA
Questo livello di memoria viene usato generalmente da dispositivi quali schede video, schede di interfaccia, ecc, che ovviamente hanno un tempo di accesso maggiore rispetto alla memoria principale.
Memoria virtuale
La memoria virtuale simula la memoria principale utilizzando lo spazio su disco ed è responsabile del trasferimento di dati dall'hard disk alla memoria principale. E' inoltre responsabile della gestione dei processi del sistema, ad esempio ipotizzando di avere in attivo 10 servizi contemporaneamente, come può la CPU decidere quale memoria far utilizzare a ciascun servizio? La risposta è il paging.
Il paging consiste nel suddividere la memoria in porzioni (per esempio da 32 bit) le quali vengono affidate ai vari processi. In questo modo ogni processo avrà i suoi indirizzi di memoria riservati (nota che per il processo 1, l'indirizzo $F è diverso dal rispettivo $F nel processo 2). La CPU userà poi in seguito una tabella di lookup per conoscere l'effettivo indirizzo, che a sua volta contiene un meccanismo di cache per evitare problemi di performance.
Esempio pratico per l'ottimizzazione del software in C
int arr[123][123]
...
for(i = 0; i < 123; i++) arr[0][0] = ..
{ arr[1][0] = ..
for(j = 0; j < 123; j++) arr[2][0] = ...
{
arr[j][i] = i + j;
}
}
vs
int arr[123][123]
...
for(i = 0; i < 123; i++) arr[0][0] = ..
{ arr[0][1] = ..
for(j = 0; j < 123; j++) arr[0][2] = ...
{
arr[i][j] = i + j;
}
}
In questi due esempi l'unica differenza risiede nell'ultima istruzione. Il C usa l'ordinamento a colonne per gestire gli array di dimensione multipla, per cui vengono salvati gli indici in posizioni continue nella cache di memoria. Tuttavia nel primo esempio l'accesso avviene in modo non naturale, causando un fenomeno descritto come trashing, mentre nel secondo caso sfruttiamo appieno le capacità della CPU.
La chiave qui sta nel fatto che è sempre meglio studiare come avviene l'accesso alla memoria qualora si stia tentando di ottimizzare il proprio codice a questi livelli (anche se sarebbe sempre da prendere come regola generale).
Conclusioni
Nella lista non è stata inclusa la gestione della memoria su disco fisso, dispositivi esterni e network.
Approfondimenti:
Posted in programmazione | Tags memory | no comments | no trackbacks
Posted by Dibi Store
Sat, 22 Mar 2008 18:01:00 GMT
Una domanda legittima che un programmatore può farsi nel corso dei suoi studi è: dov'è che esattamente viene rediretto l'output dei miei comandi?
Ad esempio in ruby, il metodo puts viene chiamato senza ricevente esplicito, quindi da qualche parte deve essere definito dove stampare la stringa.
Quando avviamo un programma in ruby, ci vengono fornite tre costanti, STDIN, STDOUT e STDERR, che indicano rispettivamente da dove prendere l'input, dove stampare l'output e infine gli errori. Queste variabili contengono degli indirizzi di memoria, possiamo verificarlo con un semplice inspect delle costanti.
A dire il vero, ruby ci mette a disposizione anche tre variabili globali ($stdin, $stdout e $stderr), che possono essere gestite direttamente da noi all'interno del programma per modifica il flusso I/O. Vediamo un esempio:
file = File.new('foo', w)
puts 'standard output'
$stdout = file
puts 'sto scrivendo all\'interno del file'
$stdout = STDOUT
puts 'sono nuovamente nel flusso standard'
Posted in ruby | Tags io | no comments | no trackbacks
Posted by Dibi Store
Thu, 20 Mar 2008 14:28:00 GMT
Il plugin acts_as_taggable_on_steroids è molto utile quando abbiamo bisogno di taggare i nostri modelli in rails. Recentemente mi sono trovato a dover implementare una funzionalità di paginazione che tenesse conto dei risultati della ricerca per tag. Come plugin per la paginazione usiamo will_paginate e per aggiungere la funzionalità mi è bastato inserire questo pezzo di codice alla fine del file environment.rb.
module ActiveRecord
module Acts
module Taggable
module SingletonMethods
def paginate_tagged_with(*args)
options = find_options_for_find_tagged_with(*args)
options.blank? ? WillPaginate::Collection.new(1, 1, 0) : paginate(:all, options)
end
end
end
end
end
Dietro le quinte stiamo definendo un metodo che usa paginate al posto di file, WillPaginate::Collection.new(1, 1, 0) serve invece per evitare di ricevere l'errore undefined method `page_count' for []:Array quando l'array di risultati è vuoto.
Posted in ruby on rails | no comments | no trackbacks