Что быстрее, выполняя итерации вектора STL с вектором:: итератор или с в ()?

Если вы активно закроете приложение (закрыв его из списка активности Android), Android, скорее всего, убьет ваш сервис. Вы можете видеть это в своих приложениях Logcat. Единственный реальный способ обойти это - обслуживание переднего плана.

Кроме того, onBind не будет вызываться при каждом подключении к услуге. Из документации Android :

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

blockquote>

Во-вторых, только то, что вызывается onStartCommand, не означает, что служба создается заново. Его можно вызывать несколько раз в течение жизненного цикла службы. Например, каждый раз, когда вызывается startService, выполняется onStartCommand, но служба не обязательно воссоздается.

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

Попробуйте добавить unbind в метод onPause своей деятельности:

@Override
void onPause() {
    super.onPause()
    unbindService(this.serviceConnectino)
}

Рабочая конфигурация может выглядеть следующим образом. Он реализует увеличение счетчика с помощью специальной сервисной функции, а не onBind:

MyBoundService.kt

package com.test

import android.app.Service
import android.content.Intent
import android.os.Binder
import android.os.IBinder
import android.util.Log

class MyBoundService : Service() {

    abstract class MyBinder: Binder() {
        abstract fun getService(): MyBoundService
    }

    val iBinder: MyBinder = object: MyBinder() {
        override fun getService(): MyBoundService {
            return this@MyBoundService
        }
    }

    private var counter = 0

    fun increment() {
        counter ++
        Log.i("MyBoundService", "Counter: ${counter}")
    }

    override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
        Log.i("MyBoundService", "startCommand");
        return super.onStartCommand(intent, flags, startId)
    }

    override fun onBind(p0: Intent?): IBinder? {
        counter++
        Log.i("MyBoundService", "Bound: ${counter}")
        return iBinder
    }

    override fun onUnbind(intent: Intent?): Boolean {
        Log.i("MyBoundService", "Unbound")
        return super.onUnbind(intent)
    }
}

MainActivity.kt

package com.test

import android.content.Intent
import android.support.v7.app.AppCompatActivity
import android.os.Bundle
import kotlinx.android.synthetic.main.activity_main.*
import android.content.ComponentName
import android.content.Context
import android.content.ServiceConnection
import android.os.IBinder
import android.util.Log
import com.test.MyBoundService

class MainActivity : AppCompatActivity() {


    private val serviceConnection: ServiceConnection = object: ServiceConnection {
        override fun onServiceDisconnected(p0: ComponentName?) {
            Log.i("MainActivity", "Service disconnected")
        }

        override fun onServiceConnected(p0: ComponentName?, p1: IBinder?) {
            Log.i("MainActivity", "Service connected")
            p1?.let {
                (p1 as MyBoundService.MyBinder).getService().increment()
            }
        }

    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        btn_create.setOnClickListener {
            val i = Intent(this@MainActivity, MyBoundService::class.java)
            startService(i)
        }

        btn_bind.setOnClickListener {
            val i = Intent(this@MainActivity, MyBoundService::class.java)
            bindService(i, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onPause() {
        super.onPause()
        unbindService(serviceConnection)
    }
}

56
задан unwind 22 April 2009 в 11:24
поделиться

11 ответов

Почему бы не написать тест и узнать?

Редактировать: Мое плохое - я думал, что рассчитывал оптимизированную версию, но это не так. На моей машине, скомпилированной с g ++ -O2, версия итератора немного медленнее , чем версия оператора [], но, вероятно, не так значительно.

#include <vector>
#include <iostream>
#include <ctime>
using namespace std;

int main() {
    const int BIG = 20000000;
    vector <int> v;
    for ( int i = 0; i < BIG; i++ ) {
        v.push_back( i );
    }

    int now = time(0);
    cout << "start" << endl;
    int n = 0;
    for(vector<int>::iterator it = v.begin(); it != v.end(); ++it) {
        n += *it;
    }

    cout << time(0) - now << endl;
    now = time(0);
    for(size_t i = 0; i < v.size(); ++i) {
        n += v[i];
    }
    cout << time(0) - now << endl;

    return n != 0;
}
27
ответ дан 26 November 2019 в 17:18
поделиться

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

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

Доступ к элементам с помощью «at»

1
ответ дан 26 November 2019 в 17:18
поделиться

Если вы используете VisualStudio 2005 или 2008, чтобы получить максимальную производительность от вектора, вам нужно определить _SECURE_SCL = 0

По умолчанию _SECURE_SCL включен, что делает итерацию по содержимому значительно медленнее. Тем не менее, оставьте его включенным в отладочных сборках, это значительно упростит отслеживание любых ошибок. Одно слово предостережения: поскольку макрос изменяет размер итераторов и контейнеров, вам нужно быть согласованным во всех единицах компиляции, которые совместно используют контейнер stl.

1
ответ дан 26 November 2019 в 17:18
поделиться

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

2
ответ дан 26 November 2019 в 17:18
поделиться

Я думаю, первый вариант быстрее.

Но он зависит от реализации. Чтобы быть уверенным, вы должны профилировать свой собственный код.

Зачем профилировать свой собственный код?

Поскольку все эти факторы будут влиять на результаты:

  • Какая ОС
  • Какой компилятор
  • Какая реализация STL использовалась used
  • Были ли включены оптимизации?
  • ... (другие факторы)
4
ответ дан 26 November 2019 в 17:18
поделиться

Как все остальные здесь говорят, сделайте тесты.

Имея Сказав это, я бы сказал, что итератор работает быстрее, поскольку at () также выполняет проверку диапазона, т. е. выдает исключение out_of_range, если индекс выходит за пределы. Эта проверка сама по себе влечет за собой некоторые накладные расходы.

5
ответ дан 26 November 2019 в 17:18
поделиться

Поскольку вы смотрите на эффективность, вы должны понимать, что следующие варианты потенциально более эффективны:

//1. Using vector<string>::iterator:

vector<string> vs = GetVector();
for(vector<string>::iterator it = vs.begin(), end = vs.end(); it != end; ++it)
{
   //...
}

//2. Using size_t index:

vector<string> vs = GetVector();
for(size_t i = 0, size = vs.size(); i != size; ++i)
{
   //...
}

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

14
ответ дан 26 November 2019 в 17:18
поделиться

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

Индексация предназначена для прямого доступа. Скобки и метод в делают это. в , в отличие от [], проверит индексирование вне границ, поэтому оно будет медленнее.

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

15
ответ дан 26 November 2019 в 17:18
поделиться

Использование итератора приводит к увеличению указателя (для увеличения) и для разыменования в разыменование указателя.
С индексом приращение должно быть одинаково быстрым, но поиск элемента включает добавление (указатель данных + индекс) и разыменование этого указателя, но разница должна быть незначительной.
at () также проверяет, является ли индекс находится в пределах, поэтому он может быть медленнее.

Результаты тестов для 500M итераций, размер вектора 10, с gcc 4.3.3 (-O3), linux 2.6.29.1 x86_64:
at () : 9158ms
operator [] : 4269ms
итератор : 3914ms

YMMV, но если использование индекса делает код более читабельным / понятным, вы должны это сделать.

36
ответ дан 26 November 2019 в 17:18
поделиться

Разница должна быть незначительной. std :: vector гарантирует, что его элементы последовательно размещаются в памяти. Поэтому большинство реализаций stl реализуют итераторы в std :: vector как простой указатель. Имея это в виду, единственное различие между двумя версиями должно заключаться в том, что первая увеличивает указатель, а вторая - индекс, который затем добавляется к указателю. Итак, я предполагаю, что вторая - может быть, на одну чрезвычайно быструю (с точки зрения количества циклов) машинную команду больше.

Попробуйте проверить машинный код, созданный вашим компилятором.

В общем, однако, советом было бы профилировать если это действительно важно. Преждевременное размышление над подобными вопросами обычно не дает вам слишком многого. Обычно ваш код '

0
ответ дан 26 November 2019 в 17:18
поделиться

Вы можете использовать этот тестовый код и сравнивать результаты! Dio it!

#include <vector> 
#include <iostream> 
#include <ctime> 
using namespace std;; 


struct AAA{
    int n;
    string str;
};
int main() { 
    const int BIG = 5000000; 
    vector <AAA> v; 
    for ( int i = 0; i < BIG; i++ ) { 
        AAA a = {i, "aaa"};
        v.push_back( a ); 
    } 

    clock_t now;
    cout << "start" << endl; 
    int n = 0; 
    now = clock(); 
    for(vector<AAA>::iterator it = v.begin(); it != v.end(); ++it) { 
        n += it->n; 
    } 
   cout << clock() - now << endl; 

    n = 0;
    now = clock(); 
    for(size_t i = 0; i < v.size(); ++i) { 
        n += v[i].n; 
    } 
    cout << clock() - now << endl; 

    getchar();
    return n != 0; 
} 
2
ответ дан 26 November 2019 в 17:18
поделиться
Другие вопросы по тегам:

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