Производительность вектора:: размер (): это с такой скоростью, как читает переменную?

Первый ответ не отражает текущую парадигму Container vs Presenter .

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

Контейнеры

Итак, правильный способ сделать это - написать ValidatorContainer, который будет иметь эту функцию как свойство и обернуть в нее форму, передав правильные реквизиты в для ребенка. Когда дело доходит до вашего представления, ваш контейнер проверки валидатора обертывает ваше представление, и представление потребляет логику контейнеров.

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

Провайдеры

Если вам нужна дополнительная конфигурация, вы можете использовать модель Provider / Consumer. Поставщик - это компонент высокого уровня, который помещается где-то рядом и под верхним объектом приложения (тот, который вы монтируете) и поставляет часть контекста или свойство, настроенное на верхнем уровне, в контекстный API. Затем я устанавливаю, чтобы элементы контейнера потребляли контекст.

Соотношения родительского / дочернего контекста не должны находиться рядом друг с другом, а только ребенок должен быть каким-то образом сгенерирован. Таким образом, хранилища Redux и функция React Router. Я использовал его для создания корневого успокоительного контекста для контейнеров для отдыха (если я не предоставляю свои собственные).

(примечание: контекстный API отмечен экспериментально в документах, но я не думаю, что это уже не так, учитывая, что его использует).

//An example of a Provider component, takes a preconfigured restful.js
//object and makes it available anywhere in the application
export default class RestfulProvider extends React.Component {
	constructor(props){
		super(props);

		if(!("restful" in props)){
			throw Error("Restful service must be provided");
		}
	}

	getChildContext(){
		return {
			api: this.props.restful
		};
	}

	render() {
		return this.props.children;
	}
}

RestfulProvider.childContextTypes = {
	api: React.PropTypes.object
};

Middleware

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

Таким образом, я мог бы вставить мой объект restful.js в промежуточное ПО и заменить мои методы контейнера независимыми действиями. Мне по-прежнему нужен компонент контейнера для обеспечения действий на уровне представления формы, но connect () и mapDispatchToProps меня покрыли.

Новый v4 response-router-redux использует этот метод для воздействия на состояние истории, например.

//Example middleware from react-router-redux
//History is our service here and actions change it.

import { CALL_HISTORY_METHOD } from './actions'

/**
 * This middleware captures CALL_HISTORY_METHOD actions to redirect to the
 * provided history object. This will prevent these actions from reaching your
 * reducer or any middleware that comes after this one.
 */
export default function routerMiddleware(history) {
  return () => next => action => {
    if (action.type !== CALL_HISTORY_METHOD) {
      return next(action)
    }

    const { payload: { method, args } } = action
    history[method](...args)
  }
}

26
задан zoli2k 2 May 2010 в 12:02
поделиться

7 ответов

Забавный вопрос.

1114 Итак, что же случилось? Хорошо, если вы выполните отладку с помощью gdb, вы увидите что-то вроде 3 переменных-членов (имена не точные):

  • _M_begin: указатель на первый элемент динамического массива
  • _M_end: указатель на один за последним элементом динамического массива
  • _M_capacity: указатель на один за последним элементом, который может быть сохранен в динамическом массиве

Реализация Таким образом, значение vector<T,Alloc>::size() обычно сводится к:

return _M_end - _M_begin;  // Note: _Mylast - _Myfirst in VC 2008

Теперь есть две вещи, которые следует учитывать при рассмотрении фактической возможной оптимизации:

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

Другими словами:

  • Если вы сохраните size самостоятельно, есть большая вероятность, что он будет таким же быстрым, как компилятор мог его получить ...
  • Но вы подвергаете себя техническому разрушению: что если вдруг вы измените вектор и не обновите переменную;)?

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

16
ответ дан Matthieu M. 28 November 2019 в 07:20
поделиться

Я всегда сохраняю vector.size () в локальной переменной (только если vector.size () не изменяется в цикле for!).
Зачем? Потому что вызывать его на каждой итерации вместо сохранения в локальной переменной намного быстрее. Вот что я испытал в своих приложениях.
Я не могу дать вам реальные цифры, но это заметно изменило.

И всем тем людям, которые жалуются на микрооптимизацию:
Когда вы пишете огромный цикл for, вы просто (просто для удовольствия) вставляете в него ненужное вычитание? Нет.

Почему бы тебе просто не профилировать это? Огромный вектор и std :: time отлично подойдут.

2
ответ дан Tara 28 November 2019 в 07:20
поделиться

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

0
ответ дан Puppy 28 November 2019 в 07:20
поделиться

Вы могли бы написать собственный функтор для тела цикла и вызывать его через std::for_each. Он выполняет итерацию за вас, и тогда ваш вопрос становится спорным. Однако вы вводите вызов функции (который может быть или не быть инклудом) для каждой итерации цикла, поэтому вам лучше всего профилировать его, если вы не получаете ожидаемой производительности.

0
ответ дан 28 November 2019 в 07:20
поделиться

Производительность vector :: size (): так же быстро, как чтение переменной?

Вероятно, нет.

Имеет значение

Наверное, нет.

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

9
ответ дан 28 November 2019 в 07:20
поделиться

В каждой реализации, которую я видел, vector :: size () выполняет вычитание ] end () и begin () , то есть это не так быстро, как чтение переменной.

При реализации вектора разработчик должен сделать выбор между тем, который должен быть самым быстрым, end () или size (), , т.е. сохранить количество инициализированных элементов или указатель / итератор на элемент после последнего инициализированного элемента. Другими словами; итерация с использованием итераторов.

Если вас беспокоит производительность size (), напишите свой индекс на основе цикла for следующим образом:

for (size_t i = 0, i_end = container.size(); i < i_end; ++i){
// do something performance critical
}
5
ответ дан 28 November 2019 в 07:20
поделиться

Насколько я понимаю из спецификации C ++ 1998 года, vector :: size () требует постоянного времени, а не линейного времени. Итак, этот вопрос, вероятно, сводится к тому, быстрее ли читать локальную переменную, чем вызывать функцию, которая делает очень мало работы.

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

11
ответ дан 28 November 2019 в 07:20
поделиться
Другие вопросы по тегам:

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