Шаблон синхронизации клиент-сервер / алгоритм?

Копирование elision - это метод оптимизации компилятора, который устраняет ненужное копирование / перемещение объектов.

В следующих случаях компилятору разрешено пропускать операции копирования / перемещения и, следовательно, не вызывать связанный конструктор:

  1. NRVO (Именованная оптимизация возвращаемого значения): If функция возвращает тип класса по значению, а выражение оператора return - это имя энергонезависимого объекта с автоматическим временем хранения (который не является параметром функции), а затем копирование / перемещение, которое будет выполняться не оптимизирующим компилятор может быть опущен. Если это так, возвращаемое значение создается непосредственно в хранилище, к которому в противном случае возвращаемое значение функции было бы перемещено или скопировано.
  2. RVO (Оптимизация возвращаемого значения): если функция возвращает неназванный временный объект, который будет перемещен или скопирован в место назначения наивным компилятором, копия или перемещение могут быть опущены в соответствии с 1.
#include <iostream>  
using namespace std;

class ABC  
{  
public:   
    const char *a;  
    ABC()  
     { cout<<"Constructor"<<endl; }  
    ABC(const char *ptr)  
     { cout<<"Constructor"<<endl; }  
    ABC(ABC  &obj)  
     { cout<<"copy constructor"<<endl;}  
    ABC(ABC&& obj)  
    { cout<<"Move constructor"<<endl; }  
    ~ABC()  
    { cout<<"Destructor"<<endl; }  
};

ABC fun123()  
{ ABC obj; return obj; }  

ABC xyz123()  
{  return ABC(); }  

int main()  
{  
    ABC abc;  
    ABC obj1(fun123());//NRVO  
    ABC obj2(xyz123());//NRVO  
    ABC xyz = "Stack Overflow";//RVO  
    return 0;  
}

**Output without -fno-elide-constructors**  
root@ajay-PC:/home/ajay/c++# ./a.out   
Constructor    
Constructor  
Constructor  
Constructor  
Destructor  
Destructor  
Destructor  
Destructor  

**Output with -fno-elide-constructors**  
root@ajay-PC:/home/ajay/c++# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors    
root@ajay-PC:/home/ajay/c++# ./a.out   
Constructor  
Constructor  
Move constructor  
Destructor  
Move constructor  
Destructor  
Constructor  
Move constructor  
Destructor  
Move constructor  
Destructor  
Constructor  
Move constructor  
Destructor  
Destructor  
Destructor  
Destructor  
Destructor  

Даже когда происходит копирование и конструктор copy / move (как будто никакой оптимизации вообще не было), в противном случае программа плохо сформирована.

Вы должны разрешить такое копирование только в тех местах, где это не повлияет наблюдаемое поведение вашего программного обеспечения. Копирование elision - единственная форма оптимизации, которая позволяет иметь (то есть elide) наблюдаемые побочные эффекты. Пример:

#include <iostream>     
int n = 0;    
class ABC     
{  public:  
 ABC(int) {}    
 ABC(const ABC& a) { ++n; } // the copy constructor has a visible side effect    
};                     // it modifies an object with static storage duration    

int main()   
{  
  ABC c1(21); // direct-initialization, calls C::C(42)  
  ABC c2 = ABC(21); // copy-initialization, calls C::C( C(42) )  

  std::cout << n << std::endl; // prints 0 if the copy was elided, 1 otherwise
  return 0;  
}

Output without -fno-elide-constructors  
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp  
root@ajay-PC:/home/ayadav# ./a.out   
0

Output with -fno-elide-constructors  
root@ajay-PC:/home/ayadav# g++ -std=c++11 copy_elision.cpp -fno-elide-constructors  
root@ajay-PC:/home/ayadav# ./a.out   
1

GCC предоставляет возможность -fno-elide-constructors отключить копирование. Если вы хотите избежать возможного копирования, используйте -fno-elide-constructors.

Теперь почти все компиляторы обеспечивают копирование при разрешении оптимизации (и если для его отключения не установлен другой параметр).

Заключение

С каждым экземпляром копии исключается одна конструкция и одно совпадение с уничтожением копии, что позволяет сэкономить время процессора, а один объект не создан, что позволяет сэкономить место в стеке кадр.

217
задан Jonas 18 December 2011 в 15:39
поделиться

3 ответа

Необходимо посмотреть на то, как распределенное управление изменениями работает. Взгляд на SVN, CVS и другие репозитории, которые справляются с работой дельт.

у Вас есть несколько вариантов использования.

  • Синхронизируют изменения. Ваш журнал изменений (или история дельты) подход выглядит хорошим для этого. Клиенты отправляют свои дельты на сервер; сервер консолидирует и распределяет дельты клиентам. Это - типичный случай. Базы данных называют эту "репликацию транзакции".

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

  • Клиент подозрителен. В этом случае необходимо сравнить клиент с сервером, чтобы определить, актуален ли клиент и нуждается в каких-либо дельтах.

необходимо следовать за базой данных (и SVN) шаблон разработки последовательной нумерации каждого изменения. Тем путем клиент может выполнить тривиальный запрос ("Какой пересмотр я должен иметь?") прежде, чем попытаться синхронизироваться. И даже тогда, запрос ("Все дельты с тех пор 2149") восхитительно прост для клиента и сервера обработать.

86
ответ дан S.Lott 23 November 2019 в 04:16
поделиться

То, в чем Вы действительно нуждаетесь, Операционное Преобразование (OT). Это может даже обслужить конфликты во многих случаях.

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

27
ответ дан Daniel Paull 23 November 2019 в 04:16
поделиться

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

13
ответ дан erikkallen 23 November 2019 в 04:16
поделиться
Другие вопросы по тегам:

Похожие вопросы: