C ++ std :: list как статическая переменная-член - проблемы с параллелизмом? - PullRequest
1 голос
/ 10 марта 2011

Я написал класс, отвечающий за отслеживание сообщений об ошибках, который использует статический std :: list для отслеживания сообщений.Из этого я делю подклассы большинства других классов, чтобы дать им возможность записывать в общий журнал ошибок.При закрытии программы журнал ошибок записывается в файл.Это многопоточное приложение, однако ... мне пришло в голову, что я мог бы спросить о проблемах здесь ...

class ErrorLogger
{
public:  
  void writeErrorMessage( string message );
  // ... etc
private:
  std::list<string> _theErrorMessages;
  // ... etc
};

Я получил несколько классов из этого.Поверхностный пример:

class MultiThreadingWidget : public ErrorLogger
{
public:
  void run()
  {
     // ...
     if( !isWorking ) 
     { writeErrorMessage( "MultiThreadingWidget::run failed()..."); };
     // ...
  }
};

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

Было бы лучше сделать шаблон ErrorLog Singleton, или это для всех практических целей одно и то же?

Исключения не являются опцией для этого проекта.

Заранее спасибо!

Ответы [ 3 ]

1 голос
/ 10 марта 2011

Я написал класс, отвечающий за отслеживание сообщений об ошибках, который использует статический std :: list для отслеживания сообщений.

он не объявлен как статический -что это такое?

РЕДАКТИРОВАТЬ: увидел, что это была опечатка, и что он должен быть объявлен статическим.однако предложение в конце ответа может помочь вам достичь максимальной скорости без ошибок в потоке.

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

Ваши проблемыв обратном направлении - нет причин вводить ошибку, которую трудно отследить и которую можно легко избежать.

В: если она почти наверняка фатальна и, таким образом (надеюсь) довольно редка, сколько будет стоить блокировка при регулярном выполнении?

A: только немного памяти (для блокировки).Вы не будете часто писать в него.

В: почему эти затраты будут значительными на данном этапе выполнения?

A: программа, вероятно, столкнулась с чем-то фатальным

Q: почему правильно написанная параллельная программа считается слишком медленной или даже медленнее однопоточной реализации на типичном оборудовании?

A: это не так.просто напишите свою программу для нынешних и будущих машин.Хорошо, в некоторых случаях это не очень хорошо, но я подозреваю, что это не так, поскольку вы пишете другие части программы для одновременного выполнения.

вы должны написать свою реализацию для параллелизма, если производительностьздесь действительно важно.

Было бы лучше сделать паттерн ErrorLog Singleton или это для всех практических целей одно и то же?

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

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

в конце, соберите все сообщения со всех регистраторов и запишите их на диск.таким образом, разные регистраторы (в разных контекстах) могут выводить свои сообщения по категориям (экземплярам) или по времени (если вы предпочитаете).

, если вы знаете, что это фатально, затем пересмотреть немедленную запись (как предлагает 0xC0DEFACE).

0 голосов
/ 10 марта 2011

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

С учетом сказанного: std::list не гарантированно является потокобезопасным.Вы можете решить эту проблему, используя мьютекс (например, используя pthreads или любую другую библиотеку потоков, которую вы уже используете), и блокируя ее перед любой записью в журнал ошибок.Если вы беспокоитесь о производительности, вы можете сделать одно из двух:

  1. Устранить ведение журнала для не отладочных сборок.Таким образом, вам не придется никаких накладных расходов, когда вы этого не хотите.Обратите внимание, что это сложнее, чем строго необходимо реализовать, если вы наследуете от своего класса отладки.

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

0 голосов
/ 10 марта 2011

Сначала никогда не ждите, чтобы войти, сделайте это как можно скорее. Если вы получили сбой или что-то еще, все незарегистрированные сообщения пропали, поэтому поместите их в этот файл журнала!

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

...