[c++] VS 2008 Многопоточное чтение строк из файла.

Discussion in 'С/С++, C#, Rust, Swift, Go, Java, Perl, Ruby' started by aladin1, 19 May 2015.

  1. aladin1

    aladin1 Member

    Joined:
    16 Sep 2009
    Messages:
    330
    Likes Received:
    29
    Reputations:
    7
    Есть файл ips.txt, в нем 10к строк вида:
    Code:
    1.1.1.1
    1.1.1.2
    2.2.2.1
    ...
    Нужно все их считать так, чтобы и потоки не "подрались"(многопоточность планирую допилить после) и чтобы производительность была не плохая, думал заюзать ReadFile(), по аналогии с WriteFile(), но пока не понял до конца как этим читать строки, мб как-то нужно загружать содержимое файла ips.txt в память и кромсать на массив через "\n" и затем работать с массивом. Видится ещё вариант с функциями типа getline(), но, боюсь скажется на скорости, вообще, не уверен, что годно в данном случае юзать подобное. Полученные строки хочу подставлять в сокет, отрабатывать каждая строка в сокете будет всего один раз, затем сразу переход к новой строке. Подскажите, чем и как лучше сделать, может у кого-то найдётся пример подобной реализации, буду благодарен.
     
  2. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    811
    Reputations:
    231
    C++ ? Так используй ifstream и getline. На скорости чего скажется? Работа с сокетом будет идти дольше чем работа с файлом, тем более никто не мешает каждому потоку забирать по несколько записей из файла. Или сделай поток-диспетчер, который будет читать из файла и помещать адреса в очередь, а потоки будут разбирать из нее. А если файл маленький, то проще все загрузить в память и не заморачиваться...
     
    _________________________
  3. M_script

    M_script Members of Antichat

    Joined:
    4 Nov 2004
    Messages:
    2,581
    Likes Received:
    1,317
    Reputations:
    1,557
    10к строк проще сразу загрузить в память
     
  4. DartPhoenix

    DartPhoenix Elder - Старейшина

    Joined:
    15 Sep 2013
    Messages:
    1,108
    Likes Received:
    8,495
    Reputations:
    25
    Похоже каждая строка это что-то вроде команды. ХитрО конечн. но лучше раздавать команды тредам уже после загрузки файла а грузить его одним куском (ну если нужна хорошая скорость, + если можно обойтись без использования объектов синхронизации - лучше обойтись без них. С ними быстрее работать точно не будет (хотя есть, конечно, APC которым можно будить треды после выдачи задания но это немного другое)) :) Если нет - в основном треде открываем файл и создаем объект синхронизации, мьютекс в простейшем случае. Ну и в каждом треде перед чтением строки - WaitForSingleObject а после - ReleaseMutex. И всего делов. А чем уж ее читать - вам виднее :)
     
    totenkopf likes this.
  5. alexey-m

    alexey-m Elder - Старейшина

    Joined:
    15 Jul 2009
    Messages:
    518
    Likes Received:
    100
    Reputations:
    37
    DartPhoenix likes this.
  6. aladin1

    aladin1 Member

    Joined:
    16 Sep 2009
    Messages:
    330
    Likes Received:
    29
    Reputations:
    7
    твой вариант оказался ближе =)
    попробовал грузить в память и посчитать строки через fstream, открывал F.open, операция с 500к строк заняла 2-3 сек, скорость приемлимая, пытаюсь ещё потестить getline, но не могу разобраться как дать ему буфер моего файла открытого через winapi, без всяких объявлений потоков ifstream и загрузки файла в них, если такое возможно, конечно:
    Code:
        int FileSize;
        int a = 0;
        char text[1000]={};
        string mystring;
        HANDLE hFile;
        DWORD WrittenSize;
        DWORD dwSize = sizeof(text);
        hFile = CreateFileA("ips.txt", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
        FileSize = GetFileSize(hFile, NULL);
        cout << FileSize << "\n";// размер выводится норм
        ReadFile(hFile, text, sizeof(text), &WrittenSize, NULL);
        While(a != 2)
        {
            getline(mystring,...); //вот тут пытался засунуть в mystring строку первую и затем вторую c последующим выводом на консоль, но не понял синтаксиса, чтобы взять именно с hFile
            cout << mystring << "\n";
            a++;
        }
    Для тестов надо, хочу в итоге понять какой из двух вариантов окажется шустрее при работе с файлом где более 100к строк.
     
    #6 aladin1, 19 May 2015
    Last edited: 20 May 2015
  7. Kaimi

    Kaimi Well-Known Member

    Joined:
    23 Aug 2007
    Messages:
    1,732
    Likes Received:
    811
    Reputations:
    231
    fstream естественно будет вносить некоторый оверхед при работе с файлом. Другой вопрос, зачем эта скорость при 100_000 строк. Какая разница грузится файл 2-3 секунды или 5-6?
    Если приспичило нативный хендл в fstream прокинуть, то можно что-нибудь такое попробовать http://stackoverflow.com/questions/...efile-but-force-the-handle-into-a-stdofstream
     
    _________________________
    aladin1 likes this.
  8. aladin1

    aladin1 Member

    Joined:
    16 Sep 2009
    Messages:
    330
    Likes Received:
    29
    Reputations:
    7
    вопрос исчерпан, потестил и то и другое, если кому интересно, вариант с getline оказался медленнее при чтении 1кк строк примерно в 2-3 раза, к тому же с ним сложнее работать новичкам =), всех благодарю
     
  9. sn0w

    sn0w Статус пользователя:

    Joined:
    26 Jul 2005
    Messages:
    1,023
    Likes Received:
    1,309
    Reputations:
    327
    но зачем? памяти сейчас не 640к явно, так что мапить файл целиком в память и дописать небольшой аналог gets который просто поинтер будет двигать, и залочить доступ через крит секцию.