Оптимизировать мой код, который имитирует базе данных


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

Объяснение

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

Текущие проблемы

Первая проблема, которая у меня сейчас (где моя программа работает медленнее) то, что я провожу больше времени, например таблица с 100 000 и 100 строк (0.325 мин, я улучшил это благодаря вашей помощи), чем 100 000 строк & 100 столбцов (1.61198 мин, тем же чем и раньше). Но с другой стороны, время доступа к некоторым данным лучше, во втором случае (в определенном примере, 47 секунд и 6079 секунд в первом случае) любая идея, почему??

Объяснение

Теперь позвольте мне напомнить вам, как мой код работает (с atached резюме моего кода)

В первую очередь у меня .файл txt имитируя таблицы базы данных со случайными строк, разделенных символом "|". Вот вам пример таблицы (7 строк и 5 столбцов). У меня тоже есть транспонированной таблице

NormalTable.txt

42sKuG^uM|24465\lHXP|2996fQo\kN|293cvByiV|14772cjZ`SN|
28704HxDYjzC|6869xXj\nIe|27530EymcTU|9041ByZM]I|24371fZKbNk|
24085cLKeIW|16945TuuU\Nc|16542M[Uz\|13978qMdbyF|6271ait^h|
13291_rBZS|4032aFqa|13967r^\\`T|27754k]dOTdh|24947]v_uzg|
1656nn_FQf|4042OAegZq|24022nIGz|4735Syi]\|18128klBfynQ|
6618t\SjC|20601S\EEp|11009FqZN|20486rYVPR|7449SqGC|
14799yNvcl|23623MTetGw|6192n]YU\Qe|20329QzNZO_|23845byiP|

TransposedTable.txt (это новый из предыдущего поста)

42sKuG^uM|28704HxDYjzC|24085cLKeIW|13291_rBZS|1656nn_FQf|6618t\SjC|14799yNvcl|
24465\lHXP|6869xXj\nIe|16945TuuU\Nc|4032aFqa|4042OAegZq|20601S\EEp|23623MTetGw|
2996fQo\kN|27530EymcTU|16542M[Uz\|13967r^\\`T|24022nIGz|11009FqZN|6192n]YU\Qe|
293cvByiV|9041ByZM]I|13978qMdbyF|27754k]dOTdh|4735Syi]\|20486rYVPR|20329QzNZO_|
14772cjZ`SN|24371fZKbNk|6271ait^h|24947]v_uzg|18128klBfynQ|7449SqGC|23845byiP|

Объяснение

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

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

Код, который считывает данные из Table.txt файл и сохранить его в памяти компьютера

int h;
do
{
    cout<< "Do you want to query the normal table or the transposed table? (1- Normal table/ 2- Transposed table):" ;
    cin>>h; 
}while(h!=1 && h!=2);

string ruta_base("C:\\Users\\Raul Velez\\Desktop\\Tables\\");
if(h==1)
{
    ruta_base +="NormalTable.txt"; // Folder where my "Table.txt" is found
}

if(h==2)
{
    ruta_base +="TransposedTable.txt";
}

string temp; // Variable where every row from the Table.txt file will be firstly stored
vector<string> buffer; // Variable where every different row will be stored after separating the different elements by tokens.
vector<ElementSet> RowsCols; // Variable with a class that I have created, that simulated a vector and every vector element is a row of my table

ifstream ifs(ruta_base.c_str());
while(getline( ifs, temp )) // We will read and store line per line until the end of the ".txt" file. 
{
    size_t tokenPosition = temp.find("|"); // When we find the simbol "|" we will identify different element. So we separate the string temp into tokens that will be stored in vector<string> buffer
    // --- NEW PART ------------------------------------
    const char* p = temp.c_str();
    char* p1 = strdup(p);

    char* pch = strtok(p1, "|");
    while(pch)
    {
            buffer.push_back(string(pch));
            pch = strtok(NULL,"|");
    }
    free(p1);

    ElementSet sss(0,buffer);
    buffer.clear();
    RowsCols.push_back(sss); // We store all the elements of every row (stores as vector<string> buffer) in a different position in "RowsCols" 
    // --- NEW PART END ------------------------------------
}

Table TablesStorage(RowsCols); // After every loop we will store the information about every .txt file in the vector<Table> TablesDescriptor
vector<Table> TablesDescriptor;
TablesDescriptor.push_back(TablesStorage); // In the vector<Table> TablesDescriptor will be stores all the different tables with all its information

DataBase database(1, TablesDescriptor);

Информация уже дал в предыдущем посте

После этого появляется доступ к информационной части. Предположим, что я хочу сделать запрос, и я прошу для ввода. Допустим, что мой запрос-это строка "н", а также последовательных кортежи "numTuples", и колонки "г". (Надо сказать, что количество столбцов определяется десятичное число "М", которые будут преобразованы в двоичные и покажет нам столбцов должно быть запрошено, например, если мне задать для столбцов 54 (00110110 в двоичном) я попрошу для столбцов 2, 3, 5 и 6). Тогда я доступ к компьютеру памяти к необходимой информации и хранить его в вектор shownVector. Здесь я покажу Вам части настоящего Кодекса.

Проблема В цикл если(ч == 2) , где данные из транспонированной таблицы доступны, беднее ¿зачем?

Код доступа к необходимой информации на мой вклад

int n, numTuples; 
unsigned long long int y;

cout<< "Write the ID of the row you want to get more information: " ;
cin>>n; // We get the row to be represented -> "n"

cout<< "Write the number of followed tuples to be queried: " ;
cin>>numTuples; // We get the number of followed tuples to be queried-> "numTuples"

cout<<"Write the ID of the 'columns' you want to get more information: ";
cin>>y; // We get the "columns" to be represented ' "y"

unsigned int r; // Auxiliar variable for the columns path
int t=0; // Auxiliar variable for the tuples path
int idTable;

vector<int> columnsToBeQueried; // Here we will store the columns to be queried get from the bitset<500> binarynumber, after comparing with a mask
vector<string> shownVector; // Vector to store the final information from the query
bitset<5000> mask;
mask=0x1;

clock_t t1, t2;
t1=clock(); // Start of the query time

bitset<5000> binaryNumber = Utilities().getDecToBin(y); // We get the columns -> change number from decimal to binary. Max number of columns: 5000

// We see which columns will be queried
for(r=0;r<binaryNumber.size();r++) //
{               
    if(binaryNumber.test(r) & mask.test(r))  // if both of them are bit "1"
    {
        columnsToBeQueried.push_back(r);
    }
    mask=mask<<1;   
}

do
{
    for(int z=0;z<columnsToBeQueried.size();z++)
    {
        ElementSet selectedElementSet;
        int i;
        i=columnsToBeQueried.at(z);
        Table& selectedTable = database.getPointer().at(0); // It simmulates a vector with pointers to different tables that compose the database, but our example database only have one table, so don't worry ElementSet selectedElementSet;
        if(h == 1)
        {

            selectedElementSet=selectedTable.getRowsCols().at(n);
            shownVector.push_back(selectedElementSet.getElements().at(i)); // We save in the vector shownVector the element "i" of the row "n"
        }

        if(h == 2)  
        {
            selectedElementSet=selectedTable.getRowsCols().at(i);
            shownVector.push_back(selectedElementSet.getElements().at(n)); // We save in the vector shownVector the element "n" of the row "i"
        }
        n=n+1;
        t++;            
    }
}while(t<numTuples);

t2=clock(); // End of the query time
showVector().finalVector(shownVector);
float diff ((float)t2-(float)t1);
float microseconds = diff / CLOCKS_PER_SEC*1000000;
cout<<"Time: "<<microseconds<<endl;

Определения классов

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

class ElementSet
{
private:
    int id;
    vector<string> elements; 

public:
    ElementSet(); 
    ElementSet(int, vector<string>); 

    const int& getId();
    void setId(int);

    const vector<string>& getElements();
    void setElements(vector<string>);

};

class Table
{
private:
    vector<ElementSet> RowsCols; 

public:
    Table(); 
    Table(vector<ElementSet>); 

    const vector<ElementSet>& getRowsCols();
    void setRowsCols(vector<ElementSet>);
};


class DataBase
{
     private:
        int id;
        vector<Table> pointer; 

     public:
        DataBase(); 
        DataBase(int, vector<Table>); 

    const int& getId();
    void setId(int);

    const vector<Table>& getPointer();
    void setPointer(vector<Table>);

    };

class Utilities
{
        public:
        Utilities();
        static bitset<500> getDecToBin(unsigned long long int);
};

Резюме моей проблемы

  • Почему загрузка данных отличается в зависимости от формата таблицы???
  • Почему доступ к информации также зависит от таблицы (и наоборот, чем таблица загрузки данных?


830
1
задан 30 марта 2011 в 04:03 Источник Поделиться
Комментарии
3 ответа

Если вы хотите оптимизировать свой код, я бы сначала предлагаю вам для профилирования кода (некоторые на Windows можно найти здесь : https://stackoverflow.com/questions/67554/whats-the-best-free-c-profiler-for-windows-if-there-are).

Программист обычно очень беден на поиск узких мест в коде и профайлер поможет вам найти, где 20% кода работать 80% времени.

Затем с thoses информацию, мы сможем дать вам лучшую помощь.

2
ответ дан 12 апреля 2011 в 10:04 Источник Поделиться

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

for(int z=0;z<columnsToBeQueried.size();z++)

Вы должны написать что-то как:

/*int size = columnsToBeQueried.size(); 
for(int z=0;z<size;z++)*/

потому что, как я думаю, граф каждый раз, когда размер columnsToBeQueried и то же

binaryNumber.size()

0
ответ дан 18 апреля 2011 в 09:04 Источник Поделиться

Вы действительно спросить, почему транспонирование таблицы деятельности принимает другое время или ты спрашиваешь для повышения производительности?

Оба вопроса имеют отношение в данном случае и я постараюсь на них ответить.

Рассматривайте это:

selectedElementSet=selectedTable.getRowsCols().at(n);

Что происходит под крышкой? Вектор копируется. Это означает, что все строки в вектор копируются. В транспонированной таблице есть 100 000 строк и в обычном есть 100. Что нужно сделать, чтобы улучшить производительность?

const ElementSet&  selectedElementSet=selectedTable.getRowsCols().at(n);

Так просто. Больше никаких копий.

После внесения этого изменения я настоятельно рекомендую читать больше на C++ и библиотеки STL. Вы будете лучше понимать как она работает и сможет устранить более "под прикрытием" проблем с вашим кодом.

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

0
ответ дан 14 ноября 2012 в 10:11 Источник Поделиться