BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Notícias O futuro do C#: ponteiros gerenciados

O futuro do C#: ponteiros gerenciados

Favoritos

Para muitos desenvolvedores, especialmente aqueles que estão construindo jogos ou analisando dados numéricos, o aspecto de desempenho é tratado com grande ênfase. E para estes desenvolvedores, nada é mais problemático do que alocação de memória. Enquanto a alocação de memória para alguns objetos é uma tarefa com pouco custo do ponto de vista computacional, a realização de muitas alocações adiciona pressão à memória e causa ciclos de coleta de lixo (garbage collection) mais frequentes.

A memória alocada no Heap também pode causar problemas para o cache. Se houver uma lista ou uma matriz (array) de tipos de referência, seus dados são armazenados separadamente da matriz. Isto significa que haverá desperdício de áreas de cache separadas para a matriz e para os objetos referenciados pela matriz. E se estes objetos foram criados ao mesmo tempo, eles podem estar espalhados na memória que talvez sejam necessárias novas áreas de cache. Este espalhamento de dados relacionados é conhecido como localização pobre (poor locality).

A utilização de tipos de valores (structs na terminologia C#) pode reduzir dramaticamente o número de alocações e melhorar a localização. Entretanto, existem limitações no que se pode fazer com tipos de valores. Como eles são projetados para serem copiados na atribuição (copy-on-assignement), é necessário manter estas estruturas com tamanho pequeno ou pode haver o risco de um sério problema de desempenho, o que invalidaria a razão de utilizá-las.

Uma maneira de reduzir o número de cópias de valores desnecessários é através da passagem de tipos de valor para funções utilizando um ponteiro gerenciado. Atualmente, a única forma de criar um ponteiro gerenciado em C# é utilizando a palavra reservada 'ref' como parte do parâmetro. Enquanto esta abordagem endereça o desempenho em alguns cenários, o CLR (Common Language Runtime) é capaz de fazer muito mais com ponteiros gerenciados.

Na proposta Ref Returns and Locals, são apresentadas mais duas opções para os desenvolvedores C#.

Ref Local

Assumindo que a é uma variável local do tipo int, a proposta sugere a criação de uma variável local por referência (Ref Local) com esta sintaxe:

ref int x = a;

Assim como um parâmetro por referência (ref parameter), uma variável local por referência (ref local) torna-se efetivamente um sinônimo para a variável local indicada, eliminando a necessidade de realizar uma cópia. Também é possível utilizá-la para obter um ponteiro para um elemento de uma matriz ou para um campo em outro objeto.

ref int y = b[2];
ref int z = c.d;

Nos termos do CLR, uma variável local por referência é chamada "TypedReference". Um "TypedReferece" contém o ponteiro para a localização na memória e a informação sobre que tipo de dado deve estar armazenado nesta localização.

Como regra, um TypedReference é sempre um parâmetro ou variável local. Isto é necessário, pois o CLR não permite que itens do heap apontem para o interior de outros itens no heap. Também não é possível retornar um TypedReference, já que isso tornaria possível retornar uma referência para um valor local que obviamente não existiria após a saída de um método.

Ref Return

A segunda parte da proposta sugere o retorno de um tipo de referência a partir de uma função. Isto permitiria cenários como:

public static ref TValue Choose(Func condition, ref TValue left, ref TValue right)
{
    return condition() ? ref left : ref right;
}
Matrix3D left = […], right = […];
Choose(chooser, ref left, ref right).M20 = 1.0;

Com esta nova sintaxe, não há cópias da estrutura em nenhum ponto do exemplo apresentado. Ao invés disso, utilizam-se ponteiros gerenciados.

De forma distinta de uma variável local por referência, a implementação desta funcionalidade pode requerer alterações no padrão do CLR. Como já mencionado anteriormente, retornar um TypedReference é algo normalmente não permitido. Tecnicamente falando é possível fazer, mas esta prática é considerada como uma prática de tipagem insegura (not type-safe) e portanto não verificável. A utilização de código não verificável não é permitida em ambientes com configurações de segurança restrita e introduz o risco de graves defeitos que normalmente só são encontrados em código C/C++.

Para mitigar este risco, parte da proposta descreve que só pode retornar uma referência para algo no heap ou para um parâmetro ref/out já existente. Em outras palavras, o compilador verificaria que não pode retornar uma referência para uma variável local.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT