Ce à quoi vous êtes confronté est le compromis classique temps-mémoire. Les champs de bits seront plus petits en mémoire, mais prendront plus de temps à fonctionner. Vous pouvez compter que quel que soit le processeur, les champs de bits seront plus lents.
Vous utilisez le mot efficace , mais ce mot n'a pas de signification certaine sans une métrique pour ce qui est bon ou mauvais. Lorsque vous n'avez que 8 ko de RAM, l'utilisation de la mémoire est mauvaise, le temps peut être bon marché. Si vous avez des contraintes de temps réel, l'utilisation du temps est mauvaise et la mémoire peut être bon marché. En général, vous ne pouvez acheter que votre moyen de sortir de ce compromis. En d'autres termes, lorsque vous trouvez le temps et la mémoire mauvais, dépensez de l'argent et utilisez une puce plus grosse. Il n'y a pas de réponse unique pour ce qui est bon ou mauvais. C'est en partie pourquoi il y a tant de choix pour les microcontrôleurs, les gens adaptent la puce à l'application et l'application à la puce.
Le remplissage des bits d'un champ de bits sera plus lent que le remplissage d'octets complets. Prenons par exemple
x = 5; ... asimplestruct.len = x; // vsabitfield.len = x;
Le premier cas simple sera juste:
- charger la valeur de x dans un registre
- le stocker dans l'octet pour len
Le second fait quelque chose comme:
- charge la valeur actuelle de abitfield
- charge un masque
- efface les bits pour len
- charge la valeur actuelle de x
- charge un masque
- efface les bits inutilisés de x
- décale les bits de x
- ou de x avec le champ abit
- stocke la valeur actuelle en mémoire
Si toutes vos opérations regroupent des données dans le champ de bits ou sortent du champ de bits, vous devriez vous attendre à une exécution plus lente. Les champs de bits sont un type de compression - ils coûtent des ticks.
Mais se déplacer dans les champs de bits sera plus rapide car il y a moins d'octets à charger et à stocker. Si vous triez ce tableau, le plus petit nombre d'octets pourrait être un avantage. Si vous les transférez via un port série, la taille compressée du champ de bits pourrait être un gagnant.
Donc en ce qui concerne votre question:
Y a-t-il un bon moyen de tester cela?
Le seul bon moyen de tester cela est d'écrire cas de test pour les deux approches en utilisant un modèle qui correspond étroitement à votre application. Le mélange d'opérations que vous effectuez est vraiment important pour décider si la différence est négligeable ou significative.
Lorsque vous faites ce type d'expérience d'optimisation, utilisez définitivement le contrôle de code source sur votre projet. Vous pouvez créer un référentiel GIT ou Mercurial local en quelques clics. Garder une chaîne de points de contrôle vous permet de déchirer votre code en explorant les effets de différentes implémentations. Si vous prenez un mauvais virage, le référentiel vous permet simplement de revenir au dernier bon point et d'essayer un autre chemin.
(Remarque: cette fois, le compromis mémoire existe également dans la direction opposée. Si vous regardez grâce aux options du compilateur pour les processeurs de classe de bureau, vous trouverez quelque chose appelé emballage de structure . Cette option vous permet d'ajouter des octets vides entre les champs à un octet de sorte qu'ils restent alignés aux limites des mots ou des doubles mots. Cela peut semble fou de jeter la RAM exprès, mais sur les processeurs avec des registres et des bus de 16 ou 32 bits de large, les opérations de mémoire alignées sur mot ou dword peuvent être plus rapides que les opérations par octet.)