Почему snprintf быстрее, чем ostringstream или является им?

В общем, лучше спросить, может ли объект выполнить данный селектор, а не проверять номер версии, чтобы решить, должен ли он присутствовать.

Если это не вариант, вам нужно будьте немного осторожны, потому что [@"5.0" compare:@"5" options:NSNumericSearch] возвращает NSOrderedDescending, который вообще не может быть предназначен; Я мог бы ожидать здесь NSOrderedSame. Это, по крайней мере, теоретическая проблема, на которую, по моему мнению, стоит защищаться.

Также стоит подумать о возможности ввода плохой версии, с которой нельзя разумно сравнить. Apple поставляет три предопределенные константы NSOrderedAscending, NSOrderedSame и NSOrderedDescending, но я могу подумать об использовании для некоторой вещи, названной NSOrderedUnordered, в случае, если я не могу сравнивать две вещи, и я хочу вернуть значение, указывающее это .

Более того, не исключено, что Apple когда-нибудь расширит свои три предопределенные константы, чтобы обеспечить множество возвращаемых значений, делая сравнение != NSOrderedAscending неразумным.

, рассмотрим следующий код.

typedef enum {kSKOrderedNotOrdered = -2, kSKOrderedAscending = -1, kSKOrderedSame = 0, kSKOrderedDescending = 1} SKComparisonResult;

@interface SKComparator : NSObject
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo;
@end

@implementation SKComparator
+ (SKComparisonResult)comparePointSeparatedVersionNumber:(NSString *)vOne withPointSeparatedVersionNumber:(NSString *)vTwo {
  if (!vOne || !vTwo || [vOne length] < 1 || [vTwo length] < 1 || [vOne rangeOfString:@".."].location != NSNotFound ||
    [vTwo rangeOfString:@".."].location != NSNotFound) {
    return SKOrderedNotOrdered;
  }
  NSCharacterSet *numericalCharSet = [NSCharacterSet characterSetWithCharactersInString:@".0123456789"];
  NSString *vOneTrimmed = [vOne stringByTrimmingCharactersInSet:numericalCharSet];
  NSString *vTwoTrimmed = [vTwo stringByTrimmingCharactersInSet:numericalCharSet];
  if ([vOneTrimmed length] > 0 || [vTwoTrimmed length] > 0) {
    return SKOrderedNotOrdered;
  }
  NSArray *vOneArray = [vOne componentsSeparatedByString:@"."];
  NSArray *vTwoArray = [vTwo componentsSeparatedByString:@"."];
  for (NSUInteger i = 0; i < MIN([vOneArray count], [vTwoArray count]); i++) {
    NSInteger vOneInt = [[vOneArray objectAtIndex:i] intValue];
    NSInteger vTwoInt = [[vTwoArray objectAtIndex:i] intValue];
    if (vOneInt > vTwoInt) {
      return kSKOrderedDescending;
    } else if (vOneInt < vTwoInt) {
      return kSKOrderedAscending;
    }
  }
  if ([vOneArray count] > [vTwoArray count]) {
    for (NSUInteger i = [vTwoArray count]; i < [vOneArray count]; i++) {
      if ([[vOneArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedDescending;
      }
    }
  } else if ([vOneArray count] < [vTwoArray count]) {
    for (NSUInteger i = [vOneArray count]; i < [vTwoArray count]; i++) {
      if ([[vTwoArray objectAtIndex:i] intValue] > 0) {
        return kSKOrderedAscending;
      }
    }
  }
  return kSKOrderedSame;
}
@end
22
задан kal 15 January 2009 в 01:20
поделиться

9 ответов

std::ostringstream не , потребовал быть медленнее, но это обычно медленнее, когда реализовано. веб-сайт FastFormat имеет некоторые сравнительные тесты .

дизайн библиотеки Standard для потоковых поддержек [намного больше чем 111] делают. Дизайн предназначен, чтобы быть расширяемым, и включает protected virtual методы, которые называют публично представленные методы. Это позволяет Вам происходить из одного из потоковых классов с обеспечением, что, если Вы перегружаетесь protect метод редактора, Вы получите поведение, которое Вы хотите. Я полагаю, что компилятор мог избежать издержек virtual вызов функции, но я не знаю ни о каких компиляторах, которые делают.

Кроме того, операции с потоками часто используют growable буферы внутренне; который подразумевает относительно медленные выделения памяти.

25
ответ дан Max Lybbert 29 November 2019 в 04:29
поделиться

Некоторые парни возможно сказали бы Вам о том, что функции не могут быть быстрее друг, чем друг, но их реализация может. Правильно я думаю, что согласился бы.

Вы вряд ли будете когда-либо замечать различие в кроме сравнительных тестов. Причина, что потоки C++ обычно склоняются , чтобы быть медленнее, состоит в том, что они намного более гибки. Гибкость чаще всего прибывает или за счет времени или за счет роста кода.

В этом случае, потоки C++ основаны на потоковых буферах. Сам по себе потоки являются просто оболочкой, которые удерживают на месте форматирование и флаги ошибки, и называют право i/o фасеты библиотеки стандарта C++ (например, num_put для печати чисел), та печать значения, хорошо отформатированные, в базовый потоковый буфер, подключенный к потоку C++.

Все это механизмы - фасеты и буферы, реализованы виртуальными функциями. В то время как нет действительно никакой метки примечание, те функции должны быть реализованы, чтобы быть медленнее, чем c stdio кулоны , что факт сделает их несколько медленнее, чем использование c stdio функции обычно (я benchmark'ed, что некоторое время назад с gcc/libstdc ++ и на самом деле заметил замедление - но который Вы едва замечаете в каждодневном использовании).

8
ответ дан Johannes Schaub - litb 29 November 2019 в 04:29
поделиться

Мы заменили некоторый stringstreams во внутренних циклах с sprintf (использующий статически выделенные буферы), и это имело большое значение, и в msvc и в gcc. Я предполагаю что управление динамической памятью этого кода:

{
  char buf[100];
  int i = 100;
  sprintf(buf, "%d", i);
  // do something with buf
}

намного более просто, чем

{
  std::stringstream ss;
  int i = 100;
  ss << i;
  std::string s = ss.str();
  // do something with s
}

, но я очень доволен общей производительностью stringstreams.

9
ответ дан user52875 29 November 2019 в 04:29
поделиться

Абсолютно это является определенным для реализации.

, Но если Вы действительно хотите знать, запишите две небольших программы и сравните их. Необходимо было бы включать типичное использование для того, что Вы имеете в виду, эти две программы должны были бы генерировать ту же строку, и Вы будете использовать профилировщика для рассмотрения информации синхронизации.

Тогда Вы знали бы.

3
ответ дан Paul Beckingham 29 November 2019 в 04:29
поделиться

Одна проблема, вероятно, была бы то, что безопасность типов, добавленная ostringstream, несет дополнительные издержки. Я не сделал никаких измерений, все же.

1
ответ дан Johann Gerell 29 November 2019 в 04:29
поделиться

Как litb сказал , стандартные потоки поддерживают много вещей, в которых мы не всегда нуждаемся. Некоторая потоковая реализация никогда избавляется от этого используемая гибкость, видит FAStream, например.

0
ответ дан Community 29 November 2019 в 04:29
поделиться

Довольно возможно что, потому что sprintf часть CRT, который записан в блоке. Эти ostringstream часть STL, и вероятно немного более в общем записанный, и имеет код/издержки ООП для контакта с.

0
ответ дан George Stocker 29 November 2019 в 04:29
поделиться

Одна причина я знаю, что printf семья функций быстрее, чем соответствующие функции C++ (суд, cin, и другие потоки) состоит в том, что последние делают typechecking. Поскольку это обычно включает некоторые запросы к перегруженным операторам, это может занять время.

На самом деле, в программировании соревнований часто рекомендуется использовать printf и др., а не cout/cin по точно этой причине.

-1
ответ дан sykora 29 November 2019 в 04:29
поделиться

Да, если вы запустите приведенную ниже функцию для нескольких миллионов чисел с помощью Visual C ++ 5.0, первая версия займет примерно вдвое больше времени, чем вторая, и даст тот же результат.

Точная компиляция зацикливаюсь на .exe и запускаю Windows timethis something.exe или Linux time something »- вот как я исследую большинство своих любопытных вопросов, связанных с производительностью. (`timethis 'доступен где-то в Интернете)

void Hex32Bit(unsigned int n, string &result)
{
#if 0
    stringstream ss;
    ss
        << hex
        << setfill('0')
        << "0x" << setw(8) << n
    ;
    result = ss.str();
#else
    const size_t len = 11;
    char temp[len];
    _snprintf(temp, len, "0x%08x", n);
    temp[len - 1] = '\0';
    result = temp;
#endif
}
0
ответ дан 29 November 2019 в 04:29
поделиться