2010-12-05 5 views
4

J'ai un code hérité qui reçoit un propriétaire, l'analyse et crée un ensemble de tableaux de char statiques (incorporés dans la classe représentant le message), pour représenter les chaînes NULL. Ensuite, les pointeurs vers la chaîne sont passés tout autour et finalement sérialisés à un certain tampon. Le profilage montre que les méthodes str*() prennent beaucoup de temps.Chaîne terminée par NULL et sa longueur

Par conséquent, je voudrais utiliser memcpy() si c'est possible. Pour l'obtenir, j'ai besoin d'un moyen d'associer la longueur avec le pointeur à la chaîne de terminaison NULL. Je pensais sur:

  • L'utilisation std::string semble moins efficace, car il nécessite l'allocation de mémoire et la synchronisation des threads.

  • Je peux utiliser std::pair<pointer to string, length>. Mais dans ce cas, je dois maintenir la longueur "manuellement".

Qu'en pensez-vous?

+1

Qu'est-ce qui vous fait penser que 'std :: string' fait une synchronisation? (ou, d'ailleurs, qu'il nécessite plus d'allocations de mémoire que vous avez de toute façon?) – jalf

Répondre

3

utilisation std::string

4

profilage montre que les méthodes str *() prennent beaucoup de temps

... Bien sûr, ils ne fonctionnant sur un réseau quelconque prend beaucoup de temps.

Par conséquent, je voudrais utiliser memcpy() si c'est possible. Pour le réaliser, j'ai besoin d'un moyen d'associer la longueur avec le pointeur à la chaîne de fin NULL. Je bien sur:

memcpy est pas vraiment plus lent que strcpy. En fait, si vous effectuez un strlen pour identifier combien vous allez memcpy alors strcpy est presque certainement plus rapide.

En utilisant std :: string semble moins efficace, car il nécessite de la mémoire allocation et la synchronisation des threads

Il peut sembler moins efficace, mais il y a beaucoup de meilleurs esprits que la vôtre ou la mienne qui ont travaillé dessus

Je peux utiliser std :: pair. Mais dans ce cas, je dois maintenir la longueur "manuellement".

C'est un moyen de gagner du temps sur le calcul de la longueur. Évidemment, vous devez maintenir la longueur manuellement. C'est ainsi que fonctionnent les fenêtres BSTR (bien que la longueur soit stockée immédiatement avant, en mémoire, dans les données de chaîne réelles). std::string. par exemple, le fait déjà ...

Qu'en pensez-vous?

Je pense que votre question est posée terriblement. Il n'y a pas de vraie question posée qui rend la réponse presque impossible. Je vous conseille de poser des questions spécifiques à l'avenir.

0

Qu'est-ce que je pense? Je pense que vous devriez faire ce que tout le monde est obsédé par la pré-optimisation. Vous devriez trouver la façon la plus obscure, la plus difficile et la plus intuitive (pour vous de toute façon) de le faire de cette manière. On dirait que vous êtes sur quelque chose avec votre pair<char*,len> avec l'idée de malloc/memcpy là. Quoi que vous fassiez, n'utilisez PAS de roues pré-existantes et optimisées qui facilitent l'entretien. Être maintenable est simplement la chose la moins importante imaginable lorsque vous êtes obsédé par des gains de performance mesurés intuitivement. De plus, comme vous le savez, vous êtes plus intelligent que ceux qui ont écrit votre compilateur et sa mise en œuvre standard. Tant et si bien que vous seriez sérieusement bête de faire confiance à leur jugement sur quoi que ce soit; vous devriez vraiment envisager de réécrire le tout vous-même parce que cela fonctionnerait mieux. Et ... la dernière chose que vous voudrez faire est d'utiliser un profileur pour tester votre intuition. Ce serait trop scientifique et méthodique, et nous savons tous que la science est un tas de couchette qui ne nous a jamais rien donné; nous savons aussi que l'intuition personnelle et la révélation ne sont jamais, jamais fausses. Pourquoi perdre le temps à mesurer avec un outil objectif quand vous avez déjà intuitivement saisi l'apparence de la situation? Gardez à l'esprit que je suis honnête à 100% à mon avis ici. Je n'ai pas d'os sarcastique dans mon corps.

+0

"gains de performance intuitivement mesurée"? L'OP indique explicitement que "le profilage montre que les méthodes str *() prennent beaucoup de temps". Votre snarkiness est complètement déplacé - l'OP peut être dirigé sur la mauvaise voie, mais en regardant un problème que le profilage identifie comme étant un goulot d'étranglement n'est certainement pas une "pré-optimisation". -1. –

+1

Nulle part le PO n'a déclaré avoir mesuré une alternative pour voir s'il y avait quoi que ce soit. D'ailleurs, comme je l'ai dit ... je suis honnête à 100%. –

+0

@Fabian: mais il s'agit de pré-optimisations pour exclure des solutions potentielles sans les étudier. – jalf

1

Votre article n'explique pas d'où proviennent les appels de fonction str*(); en passant autour de char * ne les invoque certainement pas. Identifiez les sites qui effectuent réellement la manipulation de chaîne, puis essayez de déterminer s'ils le font de manière inefficace. Un écueil commun est que strcat doit d'abord analyser la chaîne de destination pour le caractère 0 de fin. Si vous appelez strcat plusieurs fois de suite, vous pouvez vous retrouver avec un algorithme O (N^2), alors faites attention à cela. Remplacer strcpy par memcpy ne fait aucune différence significative; strcpy ne fait pas une passe supplémentaire pour trouver la longueur de la chaîne, c'est simplement (conceptuellement!) Une copie caractère par caractère qui s'arrête quand il rencontre le 0 terminant. Ce n'est pas beaucoup plus cher que memcpy, et toujours moins cher que strlen suivi de memcpy.

La meilleure façon d'améliorer les performances sur les chaînes est d'éviter les copies lorsque cela est possible. ne vous inquiétez pas de faire la copie plus rapidement, essayez plutôt de copier moins! Et cela vaut pour toutes les implémentations de chaînes (et de tableaux), que ce soit , std::string, std::vector<char>, ou une classe de chaîne/tableau personnalisée.

2

Utilisez std::string. C'est un conseil déjà donné, mais laissez-moi vous expliquer pourquoi:

Un, il utilise un schéma d'allocation de mémoire personnalisé. Vos chaînes char* sont probablement mallocées. Cela signifie qu'ils sont alignés dans le pire des cas, ce qui n'est vraiment pas nécessaire pour un char[]. std::string ne souffre pas d'alignement inutile. De plus, les implémentations communes de std::string utilisent le "Small String Optimization" qui élimine complètement une allocation de tas, et améliore la localité de référence. La taille de la chaîne sera sur la même ligne de cache que le char[] lui-même.Deux, il garde la longueur de la chaîne, ce qui est en effet une optimisation de la vitesse. La plupart des fonctions str* sont plus lentes car elles n'ont pas cette information à l'avance.

Une deuxième option serait une classe rope, par ex. de SGI. Cela sera plus efficace en éliminant certaines copies de chaîne.

Questions connexes