Вопрос о производительности...
Пишу небольшую программку, работающую с потоками в целях самообучения.
Программка простенькая, она (однопоточный режим) открывает файл, в котором содержатся записи, типа ip:port, считывает эти записи в вектор. Затем (многопоточный) считывает из вектора запись, отделят Ip и port в разные переменные.
Не так важно содержимое файла, не так важно разделение, больше всего интересует производительность.
Вот код программки:
Код: Выделить всё
#include <iostream>
#include <stdlib.h>
#include <pthread.h>
#include <vector>
#include <string.h>
#include <fstream>
#define THREADS_COUNT 3 // кол-во потоков
using namespace std;
class NodeList : public vector<string>{
private:
pthread_t pl_threads[THREADS_COUNT];
pthread_mutex_t pl_mutexLock;
ifstream pl_file;
string pl_node, pl_addr, pl_port;
NodeList::iterator pl_it;
static unsigned short count;
public:
NodeList(char *file);
~NodeList();
void readNodeFromFile();
void getAddrAndPort();
void testMethod();
static void *threadsStart(void *arg);
void *threadsWork();
};
unsigned short NodeList::count = 0;
//-----------------------------------------------------------------
NodeList::NodeList(char *file) : pl_mutexLock(PTHREAD_MUTEX_INITIALIZER){
// открываем файл
pl_file.open(file);
if(!pl_file){
perror("[!] Cannot open file");
exit(1);
}
// считываем все записи из файла в вектор
readNodeFromFile();
for(int i = 0; i < THREADS_COUNT; i++)
if(pthread_create(&pl_threads[i], NULL, threadsStart, this) != 0)
perror("[!] Cannot create thread");
for(int i = 0; i < THREADS_COUNT; i++)
pthread_join(pl_threads[i], NULL);
}
//-----------------------------------------------------------------
NodeList::~NodeList(){ cout << "count -> " << count << endl; }
//-----------------------------------------------------------------
// считываем все данные из файла и сохраняем их в вектор
void NodeList::readNodeFromFile(){
while(!pl_file.eof()){
pl_file >> pl_node;
this->push_back(pl_node);
}
pl_file.close();
}
//-----------------------------------------------------------------
/*
в вектор считались записи типа ip:port
этот метод отделит ip и port
и удалит из вектора считанную запись
*/
void NodeList::getAddrAndPort(){
size_t len;
int i;
string tmp;
if(this->empty()){
cout << "[!] No more nodes in list\n";
exit(1);
}
pl_it = this->begin();
pl_addr.clear();
pl_port.clear();
tmp = *pl_it;
len = tmp.find(":");
for(i = 0; i < len; i++)
pl_addr.push_back(tmp[i]);
i++;
for(; i < tmp.size(); i++)
pl_port.push_back(tmp[i]);
this->erase(pl_it);
}
//-----------------------------------------------------------------
void NodeList::testMethod(){ count++; }
//-----------------------------------------------------------------
void *NodeList::threadsStart(void *arg){ static_cast<NodeList *>(arg)->threadsWork(); }
//-----------------------------------------------------------------
/*
каждый поток вызовет этот метод
пока в векторе есть записи типа ip:port
мьютекс заблокируется, поток извлечёт первую запись
мьютекс разблокируется, поток пойдёт дальше
*/
void *NodeList::threadsWork(){
while(!this->empty()){
pthread_mutex_lock(&pl_mutexLock);
getAddrAndPort();
pthread_mutex_unlock(&pl_mutexLock);
testMethod();
}
}
//-----------------------------------------------------------------
int main(int argc, char *argv[]){
NodeList nList(argv[1]);
return 0;
}
Что-то здесь не так...
У меня на ноуте ОС Ubuntu 11.10 32-bit, процессор Intel двухядерный по 1.73Ghz на каждом.
В передаваемом программе файле, содержится 24048 записей типа ip:port.
Запуская программу с одним потоком (THREADS_COUNT 1), время её выполнения ~7 секунд (+2 мл сек).
Запуская программу с тремя потоками (THREADS_COUNT 3), время её выполнения также ~7 секунд (+2 мл сек).
Даже запуская программу с шестью потоками (THREADS_COUNT 6), время её выполнения также, как и раньше составляет ~7 секунд (+2 мл сек).
Т.е., сколько потоков не запускай, разницы не ощущается.
Единственное "узкое" место в программе, которое я вижу, это в методе threadsWork(), когда мьютекс блокируется. Но не может же такого быть, чтобы использование мьютексов сводило на "нет" всю пользу многопоточности.
Подскажите, в чём здесь дело? Я уже просто не могу понять, в чём "весь прикол"...