L’Apple World Wide Developer Conference 2011 è finito da un po’, e Apple ha pubblicato sul suo portale developers i video delle sessioni tecniche tenute dai suoi ingegneri durante la manifestazione. Chiunque può accederci dopo una registrazione gratuita, dall’indirizzo http://developer.apple.com/videos/wwdc/2011/.
Si tratta di interventi tecnici molto specifici, tenuti da membri di rilievo dei team di sviluppo di Apple. Oltre ad essere interessanti per il loro contenuto, la loro pubblicazione svela le novità introdotte in Lion e iOS 5, dal punto di vista dello sviluppo di software, anche a chi non essendo iscritto al Developer Program non ha a disposizione le beta release e la relativa documentazione.

Dopo essermi divorato la maggior parte dei video disponibili, quindi, mi divertirò scrivendo la mia opinione sulle novità che ritengo più importanti.

LLVM vs The Rest Of The World

Apple investe fortemente nel progetto LLVM ormai da quattro anni, e i risultati si vedono. Xcode 4.2, che verrà rilasciato assieme ad iOS 5 questo autunno, includerà quello che Apple chiama “LLVM 3.0″, che aggiunge tra le altre cose un nuovo register allocator, e supporto per il type-based alias analysis. Apple ha incluso Clang come compilatore alternativo per i linguaggi C/C++ e Objective-C già da tempo, ma la novità è che per la prima volta GCC viene ufficialmente dichiarato deprecato sia su OS X che su iOS, e che Apple incoraggia gli sviluppatori a migrare al nuovo compilatore. Non mi stupirei se tra due anni, OS X 10.8 non includesse più alcuna versione di gcc.
Tra le novità di rilievo che verranno ufficialmente introdotte con Xcode 4.2, quella che mi sta più a cuore è il supporto al C++0x. Il supporto al nuovo standard non è ancora completo, ma le novità già implementate sono tra le più importanti, come gli r-value references e i vararg templates. Xcode 4.2 includerà anche libc++, la nuova implementazione della libreria standard del C++, del progetto LLVM. Oltre a supportare al 99% tutte le caratteristiche della libreria standard di C++98 e C++0x (manca solo <atomic>), i benefici in termini di performance di libc++ rispetto all’implementazione GNU sono sbalorditivi.

Objective-C Automatic Reference Counting

Questa novità è senza dubbio la più interessante, anche dal punto di vista tecnico. Objective-C ha sempre supportato un modello abbastanza particolare di gestione della memoria. La gestione è manuale, a carico del programmatore, ma al contrario del C++, ogni oggetto ha un reference count, ovvero un contatore che tiene traccia di quanti riferimenti attivi stanno puntando all’oggetto. Quando il conteggio va a zero, il runtime dealloca l’oggetto. Assicurarsi che questo conteggio resti coerente è compito del programmatore, ma le convenzioni adottate dalle librerie di sistema rendono questo compito relativamente semplice, e abbastanza meccanico. Ciononostante, la gestione automatica della memoria è la moda del ventunesimo secolo, per cui con OS X 10.5 Apple ha introdotto in Objective-C 2.0 il supporto al garbage collection. Il garbage collector implementato da Apple funziona molto bene ma porta con se due principali problemi:

  1. Codice compilato con il garbage collector non è binary-compatible con codice compilato senza
  2. Tutti gli svantaggi di un garbage collector: pause dovute all’esecuzione del collector, uso della memoria non deterministico, ecc…

Per quest’ultimo motivo, legato a performance ed uso della memoria, Apple non ha mai reso disponibile su iOS il garbage collector dell’Objective-C. Anche su OS X, l’uso del GC non è mai diventato molto popolare…

L’Automatic Reference Counting risolve il problema della gestione della memoria in modo totalmente diverso. Con ARC, il modello di gestione della memoria del linguaggio resta reference-counted, ma ora è il compilatore ad assicurarsi che il reference count venga mantenuto coerente, al posto del programmatore, seguendo automaticamente le convenzioni di ownership che prima venivano adottate manualmente dagli sviluppatori. Il risultato è una gestione totalmente automatica della memoria, senza gli inconvenienti di inefficienza e non determinismo di un garbage collector.

Una caratteristica interessante di ARC sono i cosiddetti zeroing weak pointers. Un weak pointer è un puntatore che non trattiene l’ownership dell’oggetto, ovvero non viene considerato nel conteggio dei riferimenti attivi. Un oggetto può quindi essere deallocato anche se ci sono dei weak pointers che lo puntano. I weak pointers sono assolutamente necessari in un sistema reference-counted, per evitare i cosiddetti ref-cycles, ovvero situazioni in cui due o più oggetti si puntano a vicenda in circolo, impedendo quindi ai singoli reference count di andare a zero. Un garbage collector si accorge di questa situazione eseguendo qualche algoritmo di rilevamento dei cicli, che è il task che porta via la maggior parte del tempo in tutti i normali garbage collector. In un sistema puramente refcounted, invece, questa situazione va gestita spezzando intenzionalmente il ciclo, tramite un weak pointer. Prima di ARC, spezzare il ciclo faceva parte dell’attività di gestione della memoria manuale affidata al programmatore, che doveva però anche preoccuparsi di non lasciare dangling pointers verso oggetti ormai defunti. Una proprietà importante dei weak pointer implementati da ARC è che diventano automaticamente nulli quando l’oggetto a cui puntano viene deallocato. Ciò evita in partenza numerosi tipi di bug.

I dettagli del funzionamento di ARC sono molto interessanti dal punto di vista dell’implementazione. Una documentazione particolarmente dettagliata del funzionamento e dei criteri di design è disponibile sul sito del progetto LLVM, a questo indirizzo: http://clang.llvm.org/docs/AutomaticReferenceCounting.html
Non è un caso che questa documentazione si trovi sul sito di LLVM. Apple ha infatti implementato questa nuova caratteristica del linguaggio solo su Clang, senza toccare gcc. E visto che gli ingegneri Apple hanno più volte raccomandato di migrare prima possibile dal modello di gestione manuale ad ARC, questo fatto segna ulteriormente il deprecamento di gcc su OS X e iOS, in favore di Clang.

App Sandboxing

L’application sandboxing è l’evoluzione e l’estensione a livello dell’intero sistema operativo di un meccanismo che si vede da un po’ di tempo su tutti i principali browser web. In Chrome, ad esempio, ogni tab viene gestita da un processo diverso. Lo scopo è quello di isolare eventuali bug a singole parti dell’applicazione. Su Lion, questo concetto è supportato direttamente dal sistema operativo che offre delle semplici API per la sua implementazione, e ci aggiunge vari meccanismi di sicurezza.

L’implementazione dell’App Sandboxing si snoda in due punti. La separazione dell’applicazione in parti separate che verranno eseguite in processi diversi, e la restrizione dei privilegi di ogni singola parte.
Le API fornite dal sistema per modularizzare l’applicazione sembrano a prima vista molto semplici. Si definiscono in Xcode i vari componenti, che verranno compilati in eseguibili diversi. Solitamente, in questo tipo di sistemi il problema maggiore è la comunicazione tra i processi. Le nuove API si concentrano sulla richiesta di dati o servizi dai vari componenti, non sull’esecuzione e la comunicazione con dei processi. A seconda del servizio richiesto dall’applicazione principale (ad esempio “parsing di un file PDF”), il sistema si preoccupa di eseguire il componente giusto, e mettere le due parti in comunicazione, tramite un’API di scambio di oggetti ad alto livello, chiamato XPC. Assieme a questo meccanismo di scambio messaggi è stata aggiunta anche un’API chiamata IOSurface, basata su memoria condivisa, per la condivisione tra le varie componenti di grosse quantità di dati, buffer audio/video, ecc..

La seconda fase consiste nel definire i privilegi dei singoli moduli dell’applicazione. L’intenzione è quella di negare tutte le operazioni di cui un modulo non ha bisogno, in modo da limitare al minimo i danni causati da una falla di sicurezza di un componente. Se per esempio l’apertura e la decodifica di un file sono implementate in un modulo, questo avrà solo il permesso di leggere il filesystem, ma non di accedere alla rete. Se il contenuto del file va trasmesso via rete in qualche modo, il modulo che si occupa della trasmissione avrà il permesso di collegarsi ad un server remoto, ma non di accedere ai file. L’accesso al filesystem, in particolare, è gestito a mio avviso molto bene. Si può scegliere ad esempio, che un modulo o l’intera applicazione non abbia il permesso di accedere al filesystem se non in una particolare directory riservata ai dati dell’applicazione (dentro a qualche sottodirectory della home, di solito). Ma se si tratta, ad esempio, di una applicazione che tratta documenti dell’utente, l’accesso al filesystem va consentito per permettergli di aprire i propri documenti. Per casi come questo, le librerie di sistema fanno semplicemente il loro lavoro. Le finestre di dialogo per scegliere che file aprire o salvare, ad esempio, restituiscono un ticket che permette all’applicazione di aprire il file scelto dall’utente, ma nient’altro. Oltre all’accesso al filesystem e alla rete, è possibile decidere anche disciplinare l’accesso a dispositivi esterni, volumi rimovibili, stampanti, scanner, ecc…

Questi vincoli vengono forzati dall’OS, e se un’applicazione non li rispetta viene terminata. I vincoli del sandboxing sono specificati nel Property List dell’applicazione, per cui per far si che il meccanismo funzioni è necessario che l’applicazione sia firmata digitalmente dall’autore. La firma garantisce che l’applicazione non sia stata modificata, e quindi che i vincoli specificati dall’autore non siano stati successivamente alleggeriti. Il meccanismo si integra anche bene con il Mac App Store, che di default fornisce sempre applicazioni firmate. Sull’App Store per Lion, il Sandboxing è obbligatorio per tutte le applicazioni pubblicate sullo store, che devono per lo meno specificare i vincoli dell’applicazione principale, anche senza separare alcun modulo. La conseguenza di ciò, è che se un utente scarica dall’App Store un’applicazione di cui è scritto che “non accede alla rete” o che “non accede al filesystem”, può essere sicuro che si tratta della verità.

Nonostante il possibile overhead introdotto dalla comunicazione, sembra essere un meccanismo molto efficiente. Ad esempio, sembra che QuickTime sia stato riscritto con questo meccanismo in modo che il componente che decodifica i dati sia diverso dal componente che li visualizza a schermo. L’uso del sandboxing sembra sia stato adottato pesantemente all’interno del sistema stesso. Anche Anteprima, ad esempio, separa i componenti per la lettura e la decodifica dei file che legge, il che significa che possiamo dimenticarci quelle falle alla Acrobat che sfruttano PDF malformati per fare danni al sistema.

Tutto il resto

Di altre novità interessanti ce ne sono parecchie. Sono presenti, ovviamente, tutte le API necessarie per integrare le applicazioni con le nuove funzionalità di Lion, come Versions, Resume, e Mission Control, e l’accesso ad iCloud. C’è un nuovo framework per la crittografia. iOS 5 include GLKit, che rende molto più semplice la gestione di OpenGL ES 2.0. Su Lion, le novità di Cocoa includono un nuovo meccanismo di autolayout dei widget, e meccanismi di resolution independence simili a quelli usati nel passaggio al retina display dell’iPhone 4.

Alla fine sembra che le novità per gli sviluppatori siano interessanti quanto (e forse di più) di quelle per gli utenti finali. Bisogna solo aspettare di vedere come tutto ciò si comporta su strada. La notizia di oggi è che Lion è stato distribuito in Golden Master agli sviluppatori registrati al Developer Program, quindi basterà aspettare solo ancora un po’.

 Leave a Reply

(required)

(required)

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="" highlight="">

© 2011 Nicola Gigante Hosted by NetMDM Suffusion theme by Sayontan Sinha