1300W数据加载和查找

测试数据数量1300W.测试加载时间110秒-150秒。

测试查找速度,越靠前越快。最后一条数据耗时6-8秒

 

#include <iostream>
#include <io.h>
#include <map>
#include <thread>
#include <unistd.h>
#include <pthread.h>
#include <clocale>
#include <vector>
using namespace std;


//线程锁
static pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
//数据存储的,key为邮箱,value为行号
multimap<string,int>*datas=new multimap<string,int>;
//数据存储2,key为行号,value为行内容长度
map<int,int>*dataHnums=new map<int,int>;

int tcnt=0;
FILE* fp;
bool flag=false;
int cnt=-1;
void loadDataMap()
{
    char row[1024];
    char *tmp=row;
    int hnum=0;
    string data;
    int idx=0;
    int len=0;
    int ocnt=0;
    vector<pair<string,int> >tmpdatas;
    vector<pair<int,int> >tmphnums;
    bool isend=false;
    while(!isend)
    {
        //        cout<<1<<endl;
        //加锁
        pthread_mutex_lock(&mutex);
        if(fgets(row,1024,fp)==NULL)
        {
            //cout<<"数据读取完成,退出线程"<<endl;
            isend=true;

        }
        //如果还未结束
        if(!isend)
        {
            cnt++;
            ocnt=cnt;
        }
        pthread_mutex_unlock(&mutex);

        if(!isend)
        {
            data=row;
            len=data.length();
            idx=data.find(',');
            row[idx]=NULL;
            //尽量将插入操作放在锁外部进行,数据插入临时的栈空间
            tmpdatas.push_back(pair<string,int>(row,ocnt));
            tmphnums.push_back(pair<int,int>(ocnt,len));
        }
        if(ocnt!=0&&ocnt%100000==0)
        {
            cout<<ocnt<<endl;
            //每读取到10W数据。则将栈空间的数据填充到堆空间一次
            pthread_mutex_lock(&mutex);
            datas->insert(tmpdatas.begin(),tmpdatas.end());
            dataHnums->insert(tmphnums.begin(),tmphnums.end());
            tmpdatas.clear();
            dataHnums->clear();
            pthread_mutex_unlock(&mutex);
        }
    }
    //将剩下的数据填充到堆空间
    pthread_mutex_lock(&mutex);
    datas->insert(tmpdatas.begin(),tmpdatas.end());
    dataHnums->insert(tmphnums.begin(),tmphnums.end());
    tmpdatas.clear();
    tmphnums.clear();
    tcnt--;
    if(tcnt<=0)
    {
        flag=true;
    }
    pthread_mutex_unlock(&mutex);

}
//加载数据
void init()
{
    fp=fopen("dangdangwang.txt","r");
    if(fp==NULL)
    {
        cout<<"未找到数据文件";
        return;
    }
    clockid_t start=clock();
    //开启30条线程加载数据
    for(int i=0;i<30;i++)
    {
        tcnt++;
        thread th(loadDataMap);
        th.detach();
    }
    //等待子线程
    while(!flag)
    {
        sleep(1);
    }
    clockid_t end=clock();
    int z=0;

    cout<<"数据初始化完成:"<<datas->size()<<"耗时:"<<((double)(end-start))/CLOCKS_PER_SEC<<""<<endl;
    fclose(fp);
}

//根据条件打印n条数据
void loadDataTop(int n)
{
    FILE* fp=fopen("dangdangwang.txt","r");
    if(fp==NULL)
    {
        cout<<"未找到数据文件";
        return;
    }
    char row[1024];
    cout<<"********************************"<<endl;
    for(int i=0;i<n;i++)
    {
        if(fgets(row,1024,fp)!=NULL)
        {
            cout<<row<<endl;
        }
    }
    cout<<"********************************"<<endl;
    fclose(fp);
}

//根据行号取数据
void loadDataByHnum(int n)
{
    FILE* fp=fopen("dangdangwang.txt","r");
    if(fp==NULL)
    {
        cout<<"未找到数据文件";
        return;
    }
    int h=0;
    //计算出文件指针跳转的位置
    for(int i=0;i<n;i++)
    {
        if(dataHnums->count(i)>0)
        {
            h+=(*dataHnums)[i]+1;
        }
        else
        {
            break;
        }
    }
    //跳转指针直接读取一行
    fseek(fp,h,SEEK_SET);
    char row[1024];
    fgets(row,1024,fp);
    cout<<row<<endl;
    fclose(fp);
}
int main()
{
    init();
    while(true)
    {
        cout << "请选择需要进行的操作:1、展示前若干条数据,2、根据指定邮箱搜索数据" << endl;
        int num;
        cin>>num;
        getchar();
        if(num==1)
        {
            cout<<"请输入要展示的行数:";
            cin>>num;
            getchar();
            loadDataTop(num);
        }
        else if(num==2)
        {
            cout<<"请输入要查询的邮箱:";

            char mail[25];
            cin.getline(mail,25);
            if(datas->count(mail)<=0)
            {
                cout<<"未查询到该邮箱"<<endl;
            }
            else
            {
                auto itr=(*datas).find(mail);
                loadDataByHnum((*itr).second);
            }
        }
        else
            cout<<"输入了错误的选项:"<<num<<",请重新输入!"<<endl;
    }
    return 0;
}

 

posted @ 2017-02-20 11:35  李亚金  阅读(189)  评论(0编辑  收藏  举报