Maison >développement back-end >C++ >C IOStreams est-il toujours plus lent que printf/scanf ?

C IOStreams est-il toujours plus lent que printf/scanf ?

Barbara Streisand
Barbara Streisandoriginal
2024-11-06 15:55:02245parcourir

Is C   IOStreams Always Slower Than printf/scanf?

Stratégies pour améliorer les performances d'IOStream

La plupart des programmeurs C préfèrent les fonctions printf/scanf lors du codage en C, citant leur interface supérieure. Cependant, les IOStreams sont souvent confrontés à des problèmes de performances.

Optimisation de la mémoire tampon

L'augmentation de la taille de la mémoire tampon améliore les performances en réduisant les accès au disque dur et les appels système. Ceci peut être réalisé en accédant au streambuf sous-jacent et en modifiant son tampon :

char Buffer[N];

std::ifstream file("file.txt");

file.rdbuf()->pubsetbuf(Buffer, N);

Gestion des paramètres régionaux

Les paramètres régionaux peuvent introduire une surcharge de performances en raison d'opérations complexes telles que la conversion de caractères et filtration. Pensez à utiliser les paramètres régionaux C par défaut, conçus pour l'uniformité et les conversions minimales.

Synchronisation

La synchronisation avec stdio ne semble pas améliorer les performances. Cependant, il est possible d'accéder à un paramètre global à l'aide de std::ios_base::sync_with_stdio.

Mesures et résultats

Les résultats des performances varient considérablement en fonction de l'implémentation et de la plateforme. Certains utilisateurs ont signalé des flux C IOStreams plus rapides, tandis que d'autres ont constaté des performances plus lentes.

Code d'analyse comparative

Pour ceux qui souhaitent exécuter leurs propres tests d'évaluation, voici un exemple de code :

template <typename Func>
double benchmark(Func f, size_t iterations)
{
  f();

  timeval a, b;
  gettimeofday(&a, 0);
  for (; iterations--;)
  {
    f();
  }
  gettimeofday(&b, 0);
  return (b.tv_sec * (unsigned int)1e6 + b.tv_usec) -
         (a.tv_sec * (unsigned int)1e6 + a.tv_usec);
}

struct CRead
{
  CRead(char const* filename): _filename(filename) {}

  void operator()() {
    FILE* file = fopen(_filename, "r");

    int count = 0;
    while (fscanf(file,"%s", _buffer) == 1) { ++count; }

    fclose(file);
  }

  char const* _filename;
  char _buffer[1024];
};

struct CppRead
{
  CppRead(char const* filename): _filename(filename), _buffer() {}

  enum { BufferSize = 16184 };

  void operator()() {
    std::ifstream file(_filename, std::ifstream::in);

    file.rdbuf()->pubsetbuf(_buffer, BufferSize);

    int count = 0;
    std::string s;
    while (file >> s) { ++count; }
  }

  char const* _filename;
  char _buffer[BufferSize];
};

int main(int argc, char* argv[])
{
  size_t iterations = 1;
  if (argc > 1) { iterations = atoi(argv[1]); }

  char const* oldLocale = setlocale(LC_ALL,"C");
  if (strcmp(oldLocale, "C") != 0) {
    std::cout << "Replaced old locale '" << oldLocale << "' by 'C'\n";
  }

  char const* filename = "largefile.txt";

  CRead cread(filename);
  CppRead cppread(filename);

  bool oldSyncSetting = std::ios_base::sync_with_stdio(false);

  double ctime = benchmark(cread, iterations);
  double cpptime = benchmark(cppread, iterations);

  std::ios_base::sync_with_stdio(oldSyncSetting);

  std::cout << "C  : " << ctime << "\n"
               "C++: " << cpptime << "\n";

  return 0;
}

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn