André Nobre

ASP.NET MVC, Architecture, Debugging, Commerce Server, WinDBG...

April 2010 - Posts

Caching no .NET Framework 4.0

Olá pessoal, como estão?
Hoje vou apresentar uma mudança interessante sobre caching, em comparação com versões anteriores.

Introdução

A versão 4.0 da plataforma .NET trouxe uma mudança estrutural esperada para os recursos de Cache. Nas versão 3.5 (até SP1), a plataforma fornecia uma implementação do Cache através do namespace System.Web.Caching. Nas versões anteriores o cache estava disponível no namespace System.Web, o que criada uma dependência com as classes do ASP.NET.

Neste novo framework, o namespace System.Runtime.Caching reúne toda a API necessária para criar todas as tarefas comuns ao ASP.NET Caching de versões anteriores.

System.Runtime.Caching e MemoryCache

Tudo que precisamos para trabalhar com cache, em aplicações Web ou não, está reunido no namespace System.Runtime.Caching. A unidade básica de trabalho é a classe abstrata ObjectCache, que fornece a base para criar implementações customizadas de cache.

E como é de se esperar, a classe MemoryCache é a implementação da classe abstrata ObjectCache para armazenamento das informações em memória.

public class MemoryCache : ObjectCache, 
	IEnumerable, IDisposable

A utilização do cache é muito simples, bem parecida com o modelo anterior:

    ObjectCache cache = MemoryCache.Default;
    string fileContents = cache["filecontents"] as string;

    if (fileContents == null)
    {
        CacheItemPolicy policy = new CacheItemPolicy();
        
        List<string> filePaths = new List<string>();
        filePaths.Add("c:\\cache\\example.txt");

        policy.ChangeMonitors.Add(new 
        HostFileChangeMonitor(filePaths));

        // Fetch the file contents.
        fileContents = 
            File.ReadAllText("c:\\cache\\example.txt");
        
        cache.Set("filecontents", fileContents, policy);
    }

    Label1.Text = fileContents;

Extendendo o Cache

É possível customizar todo mecanismo de cache através de várias abordagens. ScottGu escreveu sobre isto, que você pode acessar através deste link.

Conclusão

Algo muito esperado em versões anteriores, finalmente o cache está disponível sem criar relacionamento com assemblies exclusivamente Web. Perfeito para quem desenvolve outros tipos de aplicação, usufruindo deste recurso sem carregar código desnecessário.

Abraços!

Posted: Apr 14 2010, 03:01 PM by anobre | with 2 comment(s)
Filed under: ,
Evento: Lançamento do Visual Studio 2010 e .NET 4

Olá pessoal!

Ontem fizemos mais um evento, desta vez de lançamento do Visual Studio 2010 e .NET 4, com palestras de Entity Framework e Silverlight também.

As fotos estão aqui.

Abraços a todos.

Maringá Techday

Olá pessoal!

Neste último sábado realizamos um evento em Maringá, chamado Maringá TechDay, com palestras sobre .NET 4, Siverlight e Entity Framework.

O Carlos dos Santos (um dos palestrantes) acabou de publicar um post completo sobre o evento, com fotos e tudo mais.

Acesse este link para ver o resultado.

Abraços!

Programação paralela no .NET Framework 4 – Parte II

Olá pessoal, tudo bem?

Este post é uma continuação da série iniciada neste outro post, sobre programação paralela.
Meu objetivo hoje é apresentar o PLINQ, algo que poderá ser utilizado imediatamente nos projetos de vocês.

Parallel LINQ (PLINQ)

PLINQ nada mais é que uma implementação de programação paralela ao nosso famoso LINQ, através de métodos de extensão.

O LINQ foi lançado com a versão 3.0 na plataforma .NET, apresentando uma maneira muito mais fácil e segura de manipular coleções IEnumerable ou IEnumerable<T>. O que veremos hoje é a “alteração” do LINQ to Objects, que é direcionado a coleções de objetos em memória.

A principal diferença entre o LINQ to Objects “normal” e o paralelo é que na segunda opção o processamento é realizado tentando utilizar todos os recursos disponíveis para tal, obtendo uma melhora significante de performance.

CUIDADO: Nem todas as operações ficam mais rápidas utilizando recursos de paralelismo. Não deixe de ler a seção “Performance” abaixo.

ParallelEnumerable

Tudo que a gente precisa para este post está organizado na classe ParallelEnumerable. Esta classe contém os métodos que iremos utilizar neste post, e muito mais:

  • AsParallel
  • AsSequential
  • AsOrdered
  • AsUnordered
  • WithCancellation
  • WithDegreeOfParallelism
  • WithMergeOptions
  • WithExecutionMode
  • ForAll

O exemplo mais básico de como executar um código PLINQ é utilizando o métodos AsParallel, como o exemplo:

var source = Enumerable.Range(1, 10000);

var evenNums = from num in source.AsParallel()
               where Compute(num) > 0
               select num;

Algo tão interessante quanto esta facilidade é que o PLINQ não executa sempre de forma paralela. Dependendo da situação e da análise de alguns itens no cenário de execução, talvez seja mais adequado executar o código de forma sequencial – e nativamente o próprio PLINQ faz esta escolha.  É possível forçar a execução para sempre utilizar o paralelismo, caso seja necessário. Utilize o método WithExecutionMode no seu código PLINQ.

Um teste muito simples onde podemos visualizar a diferença é demonstrado abaixo:

static void Main(string[] args)
        {
            IEnumerable<int> numbers = Enumerable.Range(1, 1000);

            IEnumerable<int> results = from n in numbers.AsParallel()
                                       where IsDivisibleByFive(n)
                                       select n;

            Stopwatch sw = Stopwatch.StartNew();
            IList<int> resultsList = results.ToList();
            Console.WriteLine("{0} itens", resultsList.Count());
            sw.Stop();

            Console.WriteLine("Tempo de execução: {0} ms", sw.ElapsedMilliseconds);

            Console.WriteLine("Fim...");
            Console.ReadKey(true);
        }

        static bool IsDivisibleByFive(int i)
        {
            Thread.SpinWait(2000000);

            return i % 5 == 0;
        }

 

Basta remover o AsParallel da instrução LINQ que você terá uma noção prática da diferença de performance.

image

1. Instrução utilizando AsParallel

image 

2. Instrução sem utilizar paralelismo

Performance

Apesar de todos os benefícios, não podemos utilizar PLINQ sem conhecer todos os seus detalhes. Lembre-se de fazer as perguntas básicas:

  1. Eu tenho trabalho suficiente que justifique utilizar paralelismo?
  2. Mesmo com o overhead do PLINQ, vamos ter algum benefício?

Por este motivo, visite este link e conheça todos os aspectos, antes de utilizar os recursos disponíveis.

Conclusão

Utilizar recursos de paralelismo é ótimo, aumenta a performance, utiliza o investimento realizado em hardware – tudo isso sem custo de produtividade. Porém, não podemos usufruir de qualquer tipo de tecnologia sem conhece-la a fundo antes. Portanto, faça bom uso, mas não esqueça de manter o conhecimento a frente da empolgação.

Abraços.

Posted: Apr 04 2010, 04:22 PM by anobre | with 2 comment(s)
Filed under: ,
Programação paralela no .NET Framework 4 – Parte I

Introdução

O avanço de tecnologia nos últimos anos forneceu, a baixo custo, acesso  a workstations com inúmeros CPUs. Facilmente encontramos hoje máquinas clientes com 2, 4 e até 8 núcleos, sem considerar os “super-servidores” com até 36 processadores :)

Da wikipedia:

A Unidade central de processamento (CPU, de acordo com as iniciais em inglês) ou o processador é a parte de um sistema de computador que executa as instruções de um programa de computador, e é o elemento primordial na execução das funções de um computador. Este termo tem sido usado na indústria de computadores pelo menos desde o início dos anos 1960[1]. A forma, desenho e implementação de CPUs têm mudado dramaticamente desde os primeiros exemplos, mas o seu funcionamento fundamental permanece o mesmo.

Fazendo uma analogia, seria muito interessante delegarmos tarefas no mundo real que podem ser executadas independentemente a pessoas diferentes, atingindo desta forma uma  maior performance / produtividade na sua execução.

A computação paralela se baseia na idéia que um problema maior pode ser dividido em problemas menores, sendo resolvidos de forma paralela. Este pensamento é utilizado há algum tempo por HPC (High-performance computing), e através das facilidades dos últimos anos, assim como a preocupação com consumo de energia, tornaram esta idéia mais atrativa e de fácil acesso a qualquer ambiente.

No .NET Framework

A plataforma .NET apresenta um runtime, bibliotecas e ferramentas para fornecer uma base de acesso fácil e rápido à programação paralela, sem trabalhar diretamente com threads e thread pool.

Esta série de posts irá apresentar todos os recursos disponíveis, iniciando os estudos pela TPL, ou Task Parallel Library.

Task Parallel Library

A TPL é um conjunto de tipos localizados no namespace System.Threading e System.Threading.Tasks, a partir da versão 4 do framework.

A partir da versão 4 do framework, o TPL é a maneira recomendada para escrever código paralelo e multithreaded.

http://msdn.microsoft.com/en-us/library/dd460717(v=VS.100).aspx

Task Parallelism

O termo “task parallelism”, ou em uma tradução live paralelismo de tarefas, se refere a uma ou mais tarefas sendo executadas de forma simultanea.

Considere uma tarefa como um método. A maneira mais fácil de executar tarefas de forma paralela é o código abaixo:

Parallel.Invoke(() => TrabalhoInicial(), () => TrabalhoSeguinte());
O que acontece de verdade?

Por trás nos panos, esta instrução instancia de forma implícita objetos do tipo Task, responsável por representar uma operação assíncrona, não exatamente paralela:

public class Task : IAsyncResult, IDisposable

É possível instanciar Tasks de forma explícita, sendo uma alternativa mais complexa ao Parallel.Invoke.

var task = new Task(() => TrabalhoInicial());
task.Start();

Outra opção de instanciar uma Task e já executar sua tarefa é:

var t = Task<int>.Factory.StartNew(() => TrabalhoInicialComValor());
var t2 = Task<int>.Factory.StartNew(() => TrabalhoSeguinteComValor());

A diferença básica entre as duas abordagens é que a primeira tem início conhecido, mais utilizado quando não queremos que a instanciação e o agendamento da execução ocorra em uma só operação, como na segunda abordagem.

Data Parallelism

Ainda parte da TPL, o Data Parallelism se refere a cenários onde a mesma operação deva ser executada paralelamente em elementos de uma coleção ou array, através de instruções paralelas For e ForEach. A idéia básica é pegar cada elemento da coleção (ou array) e trabalhar com diversas threads concomitantemente.

A classe-chave para este cenário é a System.Threading.Tasks.Parallel

// Sequential version            
foreach (var item in sourceCollection)
{
    Process(item);
}

// Parallel equivalent
Parallel.ForEach(sourceCollection, item => Process(item));

Complicado né? :)

Demonstração

Acesse aqui um vídeo com exemplos (screencast).

Cuidado!

Apesar da imensa vontade de sair codificando, tome cuidado com alguns problemas básicos de paralelismo. Neste link é possível conhecer algumas situações.

Abraços.

Posted: Apr 03 2010, 06:29 PM by anobre | with 3 comment(s)
Filed under: ,
More Posts