Будет использование нескольких потоков с производительностью справки RandomAccessFile?

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

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

Это было до того, как вы смогли получить трассировку стека, исключения имели только .printStackTrace (), поэтому мне пришлось перенаправить System.out в поток моего собственного создания, затем (new Exception ()). PrintStackTrace () ; Перенаправьте System.out обратно и проанализируйте поток. Прикольные вещи.

5
задан Michael Myers 23 June 2009 в 14:55
поделиться

6 ответов

Довольно частый вопрос. Обычно использование нескольких потоков не ускоряет работу жесткого диска. Вместо этого выполнение параллельного запроса может замедлить его.

Дисковые подсистемы, esp IDE, EIDE, SATA, предназначены для последовательного чтения / записи быстрее всех.

0
ответ дан 18 December 2019 в 05:44
поделиться

Если посмотреть на JavaDoc в RandomAccessFile, сам класс не синхронизирован. Похоже, вы можете использовать синхронный режим для операций чтения и записи. Если вы не используете синхронизированный режим, вам придется самостоятельно управлять блокировками чтения и записи, что далеко не тривиально. То же самое будет верно и для прямого java.io при использовании нескольких потоков.

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

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

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

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

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

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

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

3
ответ дан 18 December 2019 в 05:44
поделиться

By my experience from C++ development the answer is: Yes, using multiple threads can improve performance when reading files. This applies to both sequential and serial access. I proved this more than once, although i always found that the real bottlenecks are somewhere else.

The reason is, that for disk access a thread will be suspended until the disk operation has completed. But most disks today support Native Command Queueing see (SAS) or Segate (SATA) (as well as do most RAID systems) and therefore do not have to handle requests in the order you make them.

Thus if you read 4 file chunks sequential, your program will have to wait for the first chunk, then you request the second one and so one. If you request the 4 chunks with 4 threads, they may be returned all at once. This kind of optimization has limits, but it works (although i have experiences only with C++ here). I measured that multiple threads can improve sequential read performance by more than 100%.

9
ответ дан 18 December 2019 в 05:44
поделиться

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

Небольшие операции с RandomAccessFile ужасно медленными.

Для максимальной производительности вам, вероятно, лучше сразу перейти на java.nio , хотя я бы посоветовал сначала заставить что-то работать заставить его работать быстро. OTOH, помните о производительности.

3
ответ дан 18 December 2019 в 05:44
поделиться

Существует возможность отобразить в памяти плоский файл с помощью NIO. В этом случае диспетчер памяти ОС становится ответственным за перемещение разделов файла на вход и выход. Вы также можете применить блокировку региона для писателей.

1
ответ дан 18 December 2019 в 05:44
поделиться

Я провел тест с приведенным ниже кодом (извините, он в cpp). Код считывает текстовый файл размером 5 МБ с несколькими потоками, переданными в качестве аргумента командной строки.

Результаты ясно показывают, что несколько потоков всегда ускоряют программу :

Обновление: Это Мне пришло в голову, что кеширование файлов здесь сыграет свою роль. Поэтому я сделал копии файла testdata, перезагрузился и использовал другой файл для каждого запуска. Обновленные результаты ниже (старые в скобках). Вывод остается тем же.

Время работы в секундах

Машина A (двухъядерный процессор XEON, работающий под управлением XP x64 с 4 дисками 10k SAS в RAID 5)

  • 1 поток: 0,61 с (0,61 с)
  • 2 Потоки: 0,44 с (0,43 с)
  • 4 потока: 0,31 с (0,28 с) (самые быстрые)
  • 8 потоков: 0,53 с (0,63 с)

Машина B (двухъядерный ноутбук с XP с одним фрагментированным 2,5 Дюймовый привод)

  • 1 поток: 0,98 с (1,01 с)
  • 2 потока: 0,67 с (0,61 с) (самый быстрый)
  • 4 потока: 1,78 с (0. 63s)
  • 8 потоков: 2.06s (0.80s)

Исходный код (Windows):

// FileReadThreads.cpp : Defines the entry point for the console application.
//

#include "Windows.h"
#include "stdio.h"
#include "conio.h"
#include <sys\timeb.h>
#include <io.h>    

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
int threadCount = 1;
char *fileName = 0;
int fileSize = 0;
double  GetSecs(void);

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

DWORD WINAPI FileReadThreadEntry(LPVOID lpThreadParameter)

{   char tx[255];

    int index = (int)lpThreadParameter;
    FILE *file = fopen(fileName, "rt");

    int start = (fileSize / threadCount) * index;
    int end   = (fileSize / threadCount) * (index + 1);

    fseek(file, start, SEEK_SET);

    printf("THREAD %4d started: Bytes %d-%d\n", GetCurrentThreadId(), start, end);


    for(int i = 0;; i++)
    {
        if(! fgets(tx, sizeof(tx), file))
            break;
        if(ftell(file) >= end)
            break;
    }
    fclose(file);

    printf("THREAD %4d done\n", GetCurrentThreadId());

    return 0;
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////



int main(int argc, char* argv[])
{
    if(argc <= 1)
    {
        printf("Usage:  <InputFile> <threadCount>\n");
        exit(-1);
    }

    if(argc > 2)
        threadCount = atoi(argv[2]);

    fileName = argv[1];
    FILE *file = fopen(fileName, "rt");
    if(! file)
    {
        printf("Unable to open %s\n", argv[1]);
        exit(-1);
    }

    fseek(file, 0, SEEK_END);
    fileSize = ftell(file);
    fclose(file);


    printf("Starting to read file %s with %d threads\n", fileName, threadCount);
    ///////////////////////////////////////////////////////////////////////////
    // Start threads
    ///////////////////////////////////////////////////////////////////////////
    double start = GetSecs();

    HANDLE mWorkThread[255];        

    for(int i = 0; i < threadCount; i++)
    {
        mWorkThread[i] = CreateThread(
                  NULL,
                  0,
                  FileReadThreadEntry,
                  (LPVOID) i,
                  0, 
                  NULL);
    }
    WaitForMultipleObjects(threadCount, mWorkThread, TRUE, INFINITE);

    printf("Runtime %.2f Secs\nDone\n", (GetSecs() - start) / 1000.);
    return 0;
}

///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////

double  GetSecs(void)

{
        struct timeb timebuffer;
        ftime(&timebuffer);
        return (double)timebuffer.millitm + 
              ((double)timebuffer.time * 1000.) - // Timezone needed for DbfGetToday
              ((double)timebuffer.timezone * 60. * 1000.);
}
13
ответ дан 18 December 2019 в 05:44
поделиться
Другие вопросы по тегам:

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