Как показать текущую пропускную способность n theads? - PullRequest
0 голосов
/ 02 мая 2020

Представьте, что у вас есть n-Threads, которые все работают на конечной точке SOAP, чтобы получить некоторые данные и сохранить их в файловой системе. Какой лучший способ отобразить пропускную способность этих потоков за последнюю секунду?

Я пришел к следующей идее:

Все 32 (n в данном случае) потоки содержат AtomicInteger, который увеличивается каждым потоком после записи одного файла в файловую систему. Это AtomicInteger затем оценивается другим потоком (# 33), который просто существует для регистрации этого AtomicInteger, разделенного на n-Threads, оценки ETA с использованием метрик (общее количество оставленных записей / пропускная способность), сбрасывающих AtomicInteger до нуля, а затем спит одну секунду и продолжает цикл до тех пор, пока все потоки не завершат свою работу.

Однако возникает следующая проблема: блокировка AtomicInteger приведет к некоторой потере производительности (хотя я бы это учел) незначительно), и результат никогда не будет последней секундой, так как будет иметь место некоторое изменение времени блокировки.

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

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

Потоки создаются ExecutorService, а все потоки относятся к Runnable.

Ответы [ 2 ]

1 голос
/ 02 мая 2020

Я думаю, что у вас очень индивидуальные требования к сбору метрик. Я сомневаюсь, что есть какие-либо библиотеки коллекции метрик, которые делают то, что вы ожидаете. Возможно оформление микрометров GaugeCounter.

Проблема Root: Вы пытаетесь одновременно читать и записывать один и тот же ресурс с помощью n + 1 работников. Вариант использования позволяет использовать вариант шаблона разброса / сбора, где один работник может объединять работу n работников, а n работников могут читать / записывать n ресурсов, принадлежащих им самим.

Предположение: Я предполагаю, что у вас есть ссылки на все эти потоки в списке или массиве, и у вас нет файлов больше чем Integer.MAX_VALUE.

Решение: Вы можете использовать volatile int в качестве композиции в каждом потоке вместо передачи AtomicInteger извне. Эти счетчики будут монотонно увеличиваться и никогда не будут изменены или сброшены в вычислительном потоке.

Вы можете сохранить локальную копию значений int в потоке вычислений и вычесть эту локальную копию из новых значений, чтобы получить файлы, обработанные в последнюю секунду, и обновить локальную копию новыми значениями (Это будет эквивалентно сбросу счетчика на 0 для каждого потока). Кроме того, если вы можете, вы можете просто отслеживать суммирование счетчиков вместо хранения счетчика для каждого потока.

class Computation implements Runnable {

    List<Worker> workerList;
    int[] localCounters;

    boolean finished;

    public Computation(List<Worker> workerList) {
        this.workerList = workerList;
        this.localCounters = new int[workerList.size()];
    }

    @Override
    public void run() {

        while (!finished) {

            for (int i = 0; i < workerList.size(); i++) {
                localCounters[i] = workerList.get(i).getCounter();
            }

            computation();
            pause();
        }
    }

    private void computation(){
        //do your computation with localCounters
        //this.localCounters[x]
    }

    private boolean isFinished () {
        return finished;
    }

    private void pause() {
        try {
            Thread.sleep(1000L);
        }
        catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class Worker implements Runnable {

    private volatile int counter;

    @Override
    public void run() {
        // do your thing.
    }

    public int getCounter() {
        return counter;
    }
}
1 голос
/ 02 мая 2020

Самый простой способ - обновлять только n-й раз, например, только каждые 100 вызовов, если AtomicInteger является узким местом. Я бы предложил сначала использовать Atomicinteger и только тогда, когда вы видите, что есть проблема, используйте более сложное решение. Существуют библиотеки для статистики выборки, например, https://github.com/HdrHistogram/HdrHistogram, но поскольку вы хотите измерить только одну конечную точку, это не соответствует вашим потребностям.

...