Si j'ai trois valeurs distinctes qui pourraient tous en forme 32 bits, est-il logique d'utiliser un uint pour les stocker?
-
01-10-2019 - |
Question
Ce que je veux dire, que j'ai un struct
pour représenter des données et il ressemble à ceci:
struct LilStruct
{
public readonly short A;
public readonly byte B;
public readonly byte C;
public LilStruct(short a, byte b, byte c)
{
A = a;
B = b;
C = c;
}
}
A short
et deux valeurs de byte
pourrait tout ajustement en 32 bits. Ce que je me demande est (à des fins d'alignement, la performance, peu importe) si elle serait effectivement judicieux de le stocker ces données dans le format suivant à la place:
struct LilStruct
{
private readonly uint _value;
public LilStruct(short a, byte b, byte c)
{
_value = ((uint)a << 16) | ((uint)b << 8) | (uint)c;
}
public int A
{
get { return (int)(_value >> 16); }
}
public int B
{
get { return (int)(_value >> 8) & 0x000000FF; }
}
public int C
{
get { return (int)(_value & 0x000000FF); }
}
}
Est-ce inutile? Quels seraient les avantages / inconvénients?
La solution
Dans .NET, lorsque vous allez utiliser un struct
de toute façon, vous pouvez aussi bien décorer la struct avec StructLayoutAttribute
comme ceci:
[StructLayout(LayoutKind.Sequential, Pack=1)]
struct LilStruct
{
public readonly short A;
public readonly byte B;
public readonly byte C;
public LilStruct(short a, byte b, byte c)
{
A = a;
B = b;
C = c;
}
}
Cela aura pour effet que les champs sont disposés de manière séquentielle, par exemple champ B
commencera à 16 offset.
Une valeur de 1 pour Pack
signifie que les champs sont alignés aux limites de byte
.
Autres conseils
Vous ne devez considérer entasser plusieurs valeurs dans un uint si les valeurs sont étroitement liées les unes aux autres, le plus souvent passé autour ensemble, et ne sont jamais ou très rarement modifiés indépendamment les uns des autres. Le coût de déballage et remballage uint afin de modifier sa valeur rend ce très cher (la taille du code et le temps d'exécution) par rapport à seulement stocker trois octets séparément.
Lors de l'exécution sur un micro avec un total de 10K octets de RAM, d'emballage comme cela pourrait valoir la peine parce que la mémoire est plus précieuse que la vitesse d'exécution. Sur un PC de bureau normal ou même dispositif de téléphone mobile, cet emballage est probablement pas la peine.
Vous pourriez rester avec votre définition de struct, et appliquer le attribut de StructLayout avec
Ce que vous rencontrerez est un simple compromis entre la taille de vos objets de données en mémoire et le coût du traitement. Si la mémoire est une préoccupation réelle, il peut être tout simplement moins cher de jeter plus de RAM à votre machine.
Il y a quelques cas où il vaut la peine de trucs fourrer dans un entier. L'espace de stockage seul est généralement pas une bonne raison, mais si les valeurs vont être utilisées ensemble comme par exemple une clé pour un dictionnaire, un dictionnaire (INTEGER, peu importe) sera beaucoup plus rapide qu'un dictionnaire (de SomeStructure, peu importe).