Disk2vhd nuovo p2v da Sysinternals

by Marco 8. ottobre 2009 10.57

Segnalo un nuovo tool della suite “sysinternals tools” per creare dischi virtuali da una macchina fisica(physical to virtual):

Ecco il link del tool http://technet.microsoft.com/en-us/sysinternals/ee656415.aspx

La cosa più interessante oltre al fatto che ha un’interfaccia grafica molto semplice è il fatto che è possibile creare un disco virtuale mentre il sistema è on-line(senza dover fare boot o altro) in quanto sfrutta le features “Volume Snapshot” di Windows.

The difference between Disk2vhd and other physical-to-virtual tools is that you can run Disk2vhd on a system that’s online. Disk2vhd uses Windows’ Volume Snapshot capability, introduced in Windows XP, to create consistent point-in-time snapshots of the volumes you want to include in a conversion.”

Promette molto bene, stiamo a vedere.

Vota questo post per primo

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

Windows

Perchè l’applicazione in debug è più lenta?

by Marco 24. giugno 2009 14.48

Vi lascio un post che spiega in dettaglio i motivi per cui un’applicazione che “gira” in debug(F5 con Visual Studio) è sensibilmente più lenta di una senza il debugger agganciato.

Ecco il link, buona lettura

Vota questo post per primo

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

.Net | Windows

“The process cannot access the file because it is being used by another process”

by Marco 17. giugno 2009 13.50

Parlando con il mio collega Fabioriguardo un progetto che sta seguendo, abbiamo convenuto che sarebbe utile avere la possibilità di sapere se un file è in utilizzo da qualche processo, per permetterci di attendere che venga liberato per essere elaborato dalla nostra procedura.

Girando un pò in internet ho visto che la soluzione più gettonata è quella di mettere un bel(battuta) try{…}cath(IOException){…} e nel catch valutare il dafarsi.

Questa soluzione non mi piace principalmente per 3 motivi:

1)Usare le eccezioni per una cosa che potrebbe non essere una “eccezione” non mi sembra corretto, io sono della fazione che tratta le eccezioni come un evento inaspettato e non un modo per fare logiche di business.

2)Sollevare e gestire una eccezione è dispendioso e se c’è la possibilità preferisco evitare di pagare questo prezzo.

3)Spesso il tipo di eccezione non individua precisamente il problema dove sta, a meno che non facciamo del “parsing” su qualche proprietà di essa, in quanto un tipo di eccezione può raggruppare più tipo di errori.

Detto questo(attenzione ho detto non MI piace, tutto è opinabile, avete il mio contatto se volete che ne parliamo approfonditamente), ho deciso di cercare un modo più “pulito” per risolvere questo problema e sono arrivato alla soluzione che consiste nello scrivere un extension method alla classe System.IO.FileInfo che controlla attraverso l’utilizzo di una API(nello specifico CreateFile)del sistema operativo se il file in questione è utilizzato da qualche altro processo.

Il pattern di utilizzo è abbastanza semplice:

//Creo il FileInfo
var fileInfo = new FileInfo(path);
//Controllo se il file è usato
Console.WriteLine("File usato: {0}", fileInfo.IsUsingByAnotherProcess());

per poterlo utilizzare dobbiamo avere visibilità sulla classe FileInfoExtension che contiene l’extension method.

Questo metodo tuttavia non è perfetto, o meglio, soffre di “race condition” ovvero se tra la chiamata IsUsingByAnotherProcess() e l’apertura del file(per processarlo) qualcuno si mette in mezzo possiamo comunque prenderci una bella eccezione per file usato da un’altro processo, ma in quel caso possiamo correttamente gestire l’eccezione come meglio ci pare(quì si che non ci aspettavamo di trovarlo occupato di nuovo). Il caso più utile in cui questo metodo può essere usato è quando sappiamo che qualcuno potrebbe “usare” il file e poi tocca a noi…per esempio un upload di file e scheduled task che elabora il file, quì è chiaro che solo noi e l’upload possono usare il file e in ordine prevedibile. Nel caso questo non fosse il vostro caso potete gestirlo nel catch(IOException) ancora attraverso questo extension method così da essere certi che il problema sia ancora quello, riprovando succesivamente l’operazione.

Potete scaricare il codice di esempio FileInfoExtension.zip (40,61 kb)

Se qualcuno ha qualche idea migliore o qualcosa da aggiungere, prego!

------------------------

Ho mandato un feedback a microsoft sulla problematica, ma dicono che non hanno pianificato di aggiungerlo nella versione 4.0 e che qualcun altro aveva già sottolineato una mancanza in questa api, lascio il link del feedback http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=468166 , magari in una versione futura fanno qualcosa.

Correntemente valutato 3.0 da 2 utenti

  • Currently 3/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: ,

.Net | Windows

Parallel.For/ForEach e i System.Threading.Task

by Marco 9. giugno 2009 14.08

Il concetto che per avere migliori performance dobbiamo usare meno thread fisici possibili e di conseguenza meno risorse( magari 1 thread per core ), viene usato anche all’interno delle nuove Task Parallel Library ( .NET Framework 4.0 ) riguardo agli oggetti Task.

Cio significa che se abbiamo un ciclo for parallelo ( Parallel.For/ForEach ), non è detto che per ogni iterazione avremo un’oggetto Task che verrà schedulato, ma l’odierna implementazione prevede che ogni Task processi un chunk di operazioni ( iterazioni diciamo ), così da abbassare l’overhead della creazione e gestione degli stessi.

Ciò potrebbe portare a subdoli problemi, come nel caso in cui ci siano delle dipendenze tra le iterazioni che potrebbero mandare in deadlock il loop.

Se vi interessa un’approfondimento sulla tematica vi consiglio di dare una letta a questo post del pfxTeam :

http://blogs.msdn.com/pfxteam/archive/2009/05/26/9641563.aspx

VMMap un nuovo tool da Sysinternals per analizzare la memoria consumata da un processo

by Marco 23. marzo 2009 16.21


Per chi se lo fosse perso vi comunico che Sysinternals(Mark Russinovich e Bryce Cogswell), ha aggiunto ai propri tools di analisi del sistema operativo una nuova utility, si chiama VMMap e permette di avere il dettaglio sulla tipologia della memoria consumata da un processo su una macchina Windows.

L'ennesimo tool di inestimabile valore per chi fa throubleshooting sulle piattaforme Windows.

Vi lascio il link del tool http://technet.microsoft.com/sysinternals/dd535533.aspx

Correntemente valutato 4.0 da 1 utenti

  • Currently 4/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Windows

“…se hai il pc lento è perchè hai poca ram…”(Parte 2)

by Marco 18. febbraio 2009 10.17

(...continua da http://www.marcorossignoli.it/post/se-hai-il-pc-lento-e-perche-hai-poca-ram(Parte-1).aspx)

…quando un programma vuole allocare della memoria per poi utilizzarla deve prima o poi richiederla al sistema operativo attraverso delle API come ad esempio VirtualAlloc.
Quando parlo di programma, non intendo solamente il codice che noi scriviamo, ma anche ad esempio un qualsiasi runtime che effettua questa chiamata per noi.
Ad esempio il runtime .NET effettua questa operazione quando noi facciamo le new() sugli oggetti, ma fortunatamente tutta questa complessità ci è nascosta e la gestione della memoria viene fatta in modo trasparente dal garbage collector.
Per capire un pò meglio come funziona il tutto, scriviamo un pò di codice C#, precisamente una bella console application che farà in modo esplicito una richiesta di memoria virtuale al sistema operativo.

Intanto con un pò di P/Invoke permettiamo a CLR di chiamare l’API (vi consiglio questo tool per generare le firme in .NET Invoke Interop Assistant):

static class Native         
{        
      public const int MEM_RESERVE = 8192;        
      public const int PAGE_READWRITE = 4;        
      public const int MEM_COMMIT = 4096;        

      [System.Runtime.InteropServices.DllImportAttribute
        ("kernel32.dll",EntryPoint ="VirtualAlloc",SetLastError=true)]        
      public static extern System.IntPtr VirtualAlloc(
            [System.Runtime.InteropServices.InAttribute()] System.IntPtr lpAddress,
            uint dwSize,
            uint flAllocationType,
            uint flProtect);

}

 

Attraverso VirtualAlloc possiamo così richiedere memoria (virtuale, ricordiamoci che noi possiamo usare solo quella) al sistema operativo che poi utilizzeremo per fare qualcosa, come ad esempio metterci le nostre strutture dati. E adesso il main:

       static void Main(string[] args)
       {
           uint Megabyte = 1048576;           

           IntPtr memoryPointer = IntPtr.Zero;

           memoryPointer = Native.VirtualAlloc(memoryPointer,
                                                  Megabyte * 300,
                                                  Native.MEM_RESERVE,
                                                  Native.PAGE_READWRITE);

           if (memoryPointer == IntPtr.Zero )
               throw new Win32Exception();

           Console.ReadKey();
       }

Il codice richiede semplicemente 300 megabyte di memoria virtuale sulla quale il processo possa scrivere e leggere.
In caso l’API ritorni null (IntPtr.Zero) significa che non c’è sufficiente memoria e l’allocazione non è andata a buon fine (ad esempio se noi mettiamo 3000 invece che 300 l’API ci risponde picche in quanto abbiamo visto che lo spazio di indirizzamento di default per lo user mode è di 2GB quindi non è possibile fare un’allocazione superiore a quella).

Se guardiamo bene il codice ci accorgiamo che l’API ci richiede un parametro particolare nel quale io ho passato MEM_RESERVE, questo significa che il sistema operativo non mi mette a disposizione subito 300 megabyte di ram fisica, ma semplicemente richiedo che mi vengano riservati 300 megabyte dello spazio di indirizzamento che succesivamente renderò fisici richiedendolo attraverso la stessa api, ma passando il parametro MEM_COMMIT. Riservarsi memoria virtuale non significa che posso metterci qualcosa, ma semplicemente mi permette di creare un blocco di memoria e avere la sicurezza che quando ne farò il commit (quindi verrà fisicamente messa a disposizione) avrò un insieme di locazioni contigue in memoria, nelle quali potrò mettere quello che mi serve.

Detto questo si capisce che abbiamo 2 tipi memoria nel nostro processo, la memoria virtuale e la memoria fisica effettivamente utilizzabile, tecnicamente chiamata “committed memory” alla quale mi riferirò sempre attraverso indirizzi virtuali. Quindi la memoria effettiva consumata dal mio processo non è quella virtuale ma quella committed ovvero quella che è stata effettivamente mappata ad indirizzi fisici.
Per provare questo comportamento possiamo fare un test e verificare che riservare memoria virtuale non consuma effetivamente la memoria fisica del sistema. Per effettuare questo test dovete scaricarvi un tool Process Explorer di Mark Russinovich, un architetto del core di Windows che lavora nel team di microsoft e co-autore del libro che vi ho segnalato come fonte.
A questo punto eseguiamo il codice che segue e guardiamo un pò di numeri:

1 static void Main(string[] args)
2         {
3            uint Megabyte = 1048576;           

4            IntPtr memoryPointer = IntPtr.Zero;

5            memoryPointer = Native.VirtualAlloc(memoryPointer,
                                                    Megabyte * 300,
                                                    Native.MEM_RESERVE,
                                                    Native.PAGE_READWRITE);

6            if (memoryPointer == IntPtr.Zero )
                 throw new Win32Exception();

7           memoryPointer = Native.VirtualAlloc(memoryPointer,
                                                   Megabyte * 300,
                                                   Native.MEM_COMMIT,
                                                   Native.PAGE_READWRITE);

8            Console.ReadKey();
9        }


Tanto per cominciare vediamo a quanto ammonta la committed memory nel mio sistema nel momento in cui scrivo. Per vederla ho cliccato sull’icona  icona  nella barra sotto il menù classico.
Ecco i risultati:

  info

Circa 2.9 di memoria fisica allocata. Nel riquadro Commit Charge vediamo le stime meno approssimative.

Ora facciamo partire il nostro programma…mettiamo un bel breakpoint alla riga numero 6 e vediamo lo stato della memoria:

infoVirtual

come possiamo notare è cambiato poco niente…un pò di committed in più ma poca roba (qualcosa ha dovuto caricare, alla fine un processo in più in memoria c’è e fino al breakpoint ci siamo arrivati, da qualche parte quei byte li dobbiamo mettere). Quindi possiamo affermare che allocare memoria virtuale non consuma memoria fisica effettiva.

Ora mettiamo un’altro breakpoint alla riga 8 e vediamo:

InfoCommited

come possiamo vedere ora stiamo consumando circa 300 megabyte di memoria fisica (committed memory) in più (non sono precisamente 300 ma un pò di più…ma sul mio pc girano molti processi e quello è un counter globale, chissà quale altro processo ha richiesto qualcosa :-) ). Quindi possiamo affermare una volta per tutte che la memoria virtuale non è la memoria realmente utilizzata.

Vediamo ora il consumo di memoria dalla prospettiva del nostro processo. Per fare questo dovete impostare un paio di contatori utili. Andate sul menù View->Select Columns->Process Memory e fleggate Private Bytes e Virtual Size.
Il contatore Private Bytes tiene conto della committed memory consumata dal processo, mentre Virtual Size è semplicemente la memoria virtuale riservata per quel processo. Attenzione quello che ho scritto non è propriamente vero o meglio è impreciso, un processo può consumare memoria fisica privatamente (Private Bytes), ma potrebbe anche consumare memoria fisica attraverso l’utilizzo delle “page file backed section” che sono delle zone di committed memory condivise con altri processi(vengono chiamate così in quanto possono essere scritte sul file di paging se serve, vedi section objects) che non vengono conteggiate nel counter di un processo.

Passiamo ai numeri:

le colonne sono rispettivamente PID (id del processo) Virtual Size e Private Byte

Riga 6

Process1

Riga 8

Process2

Ancora una volta possiamo notare la differenza tra memoria virtuale e committed memory (memoria fisica allocata).

Quindi diciamo che la somma di tutta la committed memory di tutti i processi che girano nel nostro sistema ci da più o meno la stima di quanta RAM ci serve…(anche quì ho omesso le “page file backed section” e qualche altro dettaglio per semplicità).

Un ultimo cenno aspetta al paging file; in caso la memoria fisica fosse troppo poca per far girare i nostri programmi, windows può avvalersi del disco fisso come storage temporaneo, permettendoci così di aumentare il “commit limit” del nostro pc. Chiaramente il codice e i dati di un programma devono essere in RAM per essere utilizzati quindi sarà compito del sistema operativo usare policy di “caricamento” e “scaricamento” sul file di paging delle pagine di memoria meno utili. Perciò aumentare il file di pagin significa semplicemente avere più committed memory disponibile, certo se per esempio (esagerato ma è per rendere l’idea) abbiamo 2GB di ram e abbiamo bisogno di 6GB di page file per non andare in out of memory significa che la nostra attività consuma mediamente 4 volte la ram fisica che ho (2GB fisica + 6GB file di paging) e in questo modo l’attività di paging (scrivere sul file di paging e leggere da esso) potrebbe peggiorare seriamente le prestazioni della macchina. Quindi non esiste una formula assoluta per dimensionare il file di pagin, ma possiamo controllare il nostro utilizzo medio per esempio guardando per un periodo alla sera prima di andare a casa il contatore Peak (riquadro Commit Charge) con Process Explorer (vedi sopra) e fare la differenza con il contatore Total (riquadro Physical Memory) così da vedere di quanta memoria in più abbiamo mediamente bisogno, impostando il file di paging intorno a quel numero.

Spero con questi 2 blog di aver chiarito meglio il motivo per cui, se il pc è lento, non è sempre colpa della RAM, ma per saperlo con certezza servono come sempre i numeri…l’idea di questo post mi è venuta quando l’azienda che mi fa l’hosting di un server fisico mi ha consigliato di aumentare la ram se volevo passare da Sql Server 2005 a Sql Server 2008, ho risposto che per ora i numeri non mi dicono che serve un upgrade di RAM ;-)

…chissà se l’indovino aveva ragione…

Fonti: http://www.microsoft.com/learning/en/us/Books/6710.aspx

Correntemente valutato 5.0 da 2 utenti

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , , ,

Windows

“…se hai il pc lento è perchè hai poca ram…”(Parte 1)

by Marco 17. febbraio 2009 15.17

Il titolo del blog è volutamente provocatorio (anche se questa frase la sento spesso da persone tecniche e non), almeno che chi ha detto quella frase non sia un mago o un indovino e cercherò di chiarirlo in questo post e nei seguenti.

Quando lanciamo un programma più volgarmente detto “un exe” o “eseguibile”, generalmente usiamo direttamente o indirettamente una delle APIs forniteci dal sistema operativo le quali iniziano solitamente con ‘CreateProcess…’( http://msdn.microsoft.com/en-us/library/ms682425.aspx )
Creare un processo vuol dire tra le altre cose mettere a disposizione del nostro “exe” un insieme di indirizzi di memoria dove il codice del programma possa essere caricato ed eseguito (dalla CPU) e dove i dati gestiti dallo stesso possano essere immagazzinati e usati.
Il nostro programma farà inoltre utilizzo di determinati servizi messi a disposizione del sistema operativo come ad esempio una finestra o un file, il che comporta che lo stesso SO debba mettere da qualche parte le varie strutture di memoria che gli permettono di funzionare (drivers e varie parti del so stesso…etc…).
Tutta questa memoria per essere correttamente utilizzata dal processore deve essere chiaramente nella famosa memoria chiamata RAM.
Detto questo, abbiamo capito che un programma per funzionare, deve usare della memoria allocata dal processo stesso (l’ ‘exe’ lanciato) e un’altra parte di memoria già esistente e gestita dal sistema operativo. Per evitare che chi scrive programmi possa rendere il sistema instabile andando ad esempio a scrivere sulla memoria gestita dal sistema operativo, il sistema stesso con l’aiuto dell’hardware protegge le sue locazioni dall’accesso “non legale” attraverso il concetto di “user mode” e “kernel mode”. Quando il programma  “gira” in “user mode” significa che ha accesso solo alla parte di indirizzi che non sono gestiti dal sistema operativo e in caso venga toccato un indirizzo di questo tipo, il sistema operativo  stesso, con l’aiuto dell’hardware, solleva un’eccezione avvisando che il processo sta utilizzando una parte di memoria che in “user mode” non può toccare. Quando viene effettuata una chiamata ad una API del sistema operativo che fa utilizzo di risorse (memoria) che servono alla funzionalità stessa, con una particolare istruzione macchina, l’esecuzione del codice passa da “user mode” a “kernel mode” permettendo al codice (diciamo codice del sistema operativo…drivers, APIs etc…) di accedere a qualsiasi locazione di memoria disponibile. Quando l’API ha finito il lavoro per la quale è stata chiamata avviene il processo inverso, ovvero il codice ritorna a “girare” in “user mode”, così il nostro codice scritto “male” non può danneggiare la memoria “importante” evitandoci un bel pò di blue screen.
Ora il sistema operativo ci permette di eseguire più processi contemporaneamente (multitasking) quindi serve un modo per poter virtualizzare la memoria che un processo utilizza facendogli credere di aver a disposizione la sua parte della stessa e di poter diciamo chiamare delle APIs (del sistema operativo) che a sua volta useranno una parte di memoria a loro adibita. A questo scopo esiste proprio un tipo di memoria chiamata “memoria virtuale” , una sorta di interfaccia verso l’effettiva memoria…indirizzi relativi, ecco li potremmo definire così. Ogni volta che lanciamo un programma lo stesso è convinto di avere una memoria tutta per lui a cui si riferirà in modo virtuale, sarà poi compito del sistema operativo con la collaborazione dell’hardware tradurre quell’indirizzo virtuale in una cella di memeoria fisica. Per farvi un’idea un pò più reale dovreste immaginarvi la memoria come un array di byte, solo che se voi scrivete memoriaVirtuale[27] effettivamente state accedendo alla memoriaFisica(ram)[1434] (che a noi frega poco).

Tecnicamente parlando, per default Windows su un sistema x86 (senza particolari impostazioni che cambiano le cose, vedi PAE-Physical Address Extension) utilizza una struttura a 2 livelli per tradurre un indirizzo virtuale in un indirizzo fisico, un indirizzo a 32bit viene diviso in 3 componenti che sono indici che vengono usati nelle strutture che effettuano il mapping, 10bits per le "page directory index", 10bits per le "page table index" e 12bits come "byte index" per un totale di 32bits.

Questo meccanismo permette quindi al nostro programma di non dover sapere quanta memoria fisica è disponibile (magari molto meno di quella usata da tutti i processi insieme…mah potremmo buttarla sul disco fisso; sarà lento ma meglio che non far partire il programma…insomma la paginiamo e se serve la ricarichiamo e scarichiamo qualcosa d’altro che non è utilizzato) e inoltre possiamo far girare più processi completamente isolati tra loro (esclusa la parte di memoria del SO che tanto condividiamo, tanto le funzionalità messe a disposizione dal SO ai processi sono sempre quelle o no? Quella basta proteggerla dai programmi fatti male :-P cioè se memoriaVirtuale[1] magari memoriaFisica(ram)[23459] è del sistema operativo…ci prendiamo una bella eccezione, solo il codice che gira in kernel mode può usarla).

Per concludere questo primo post diciamo che ogni processo su una macchina a 32bit ha la propria memoria virtuale di 2^32; quindi 4GB divisi tra user mode e kerner mode in questo modo (per default, ma il layout potrebbe cambiare in caso di particolari impostazioni) :

                                                    image_thumb_12


Bene…prendete fiato…nel prossimo post continuiamo a cercare di capire se l’indovino è bravo o no :-)

Fonti: http://www.microsoft.com/learning/en/us/Books/6710.aspx

Vota questo post per primo

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags: , ,

Windows

Disclaimer
Le opinioni espresse in questo blog sono mie opinioni personali.

© Copyright 2012 Knowledge.CreateAsync()