Вызов другого приложения из bash в многопроцессорной среде Python выполняется очень медленно - PullRequest
0 голосов
/ 25 февраля 2019

Я пытаюсь использовать qark анализатор для анализа набора apks в многопроцессорной обработке с использованием python.

Пытаясь проанализировать набор из 100 apks, я обнаружил, что приложение Iнаписал, чтобы автоматизировать анализ очень медленно.Последний анализ, который я выполнял, оставался в работе около 20 часов, а затем я вручную выключил свой компьютер, поскольку он стал непригодным для использования, вероятно, из-за интенсивного использования ОЗУ ... Анализ был даже вреден, испортил мой раздел Windows и не дает мне больше видеть данные внутри раздела и Windows для загрузки (я запускаю анализ из ubuntu, но в свой раздел Windows из-за свободного места на диске)

Выполнено ядро ​​классав этом процессе что-то очень похоже на

 def scanApk(self):

    try:

        #Creating a directory for qark build files (decompiled sources etc...)
        buildDirectoryPath = os.path.join(os.path.join(self.APKANALYSIS_ROOT_DIRECTORY, "qarkApkBuilds"), "build_" + self.apkInfo["package_name"])

        os.mkdir(buildDirectoryPath)

        start = timer()

        subp = subprocess.Popen(self.binPath + "/qark --report-type json --apk \"" + self.apkPath + "\"", cwd=buildDirectoryPath, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE,
            preexec_fn=os.setsid)

        #Setting a timeout of 6 hours for the analysis
        out, err = subp.communicate(timeout= 6 * (60 * 60))

        self.saveOutAndErr(out, err)


        if subp.returncode != 0:

            raise subprocess.CalledProcessError(subp.returncode, "qark")

        self.printAnalysisLasting(start)


        #Moving qark report into qark reports collecting directory
        subp = subprocess.Popen("mv \"" + self.defaultReportsPath + "/" + self.apkInfo["package_name"] + ".json\" " + "\"" + self.toolReportsDirectory + "\"", shell=True)

        out, err = subp.communicate()


        if subp.returncode != 0:

            raise subprocess.CalledProcessError(subp.returncode, "qark")


        return True

[... subprocess.TimeoutExpired and subprocess.CalledProcessError exceptions handling...]

Я использую класс в многопроцессорной обработке с использованием concurrent.futures ' ProcessPoolExecutor , как это (метод scanApk вызывается внутри analyAApkmethod):

with concurrent.futures.ProcessPoolExecutor(max_workers = 10) as executor:

        futuresList = []

        #Submitting tasks to ProcessPoolExecutor

        for apkPath in apksToAnalyzePaths:

            ...

            qarkAnalyzer = QarkAnalyzer(...)

            futuresList.append(executor.submit(qarkAnalyzer.analyzeApk))


        for future in futuresList:

            future.result()

Это, вместо этого, снимок состояния процессов во время анализа 2 apks, показанного htop:

enter image description here

Я протестировал приложение с анализом в 2 apks, и оно, похоже, ведет себя "хорошо" ... Я испытал увеличение времени выполнения qark apk analysiС уважением к выполнению единственного анализа на этом apk, но я приписал это многопроцессорности и, увидев, что это не слишком много, я подумал, что это может быть хорошо ... Но для 100 apks выполнение привело к катастрофе.

Может ли кто-нибудь помочь выяснить, что здесь происходит?Почему анализ такой медленный?Как это могло испортить мой раздел Windows?Заряд оперативной памяти слишком велик для анализа такого количества apks?Это из-за неправильного использования процессов в моем приложении?Как я могу сделать это правильно?

1 Ответ

0 голосов
/ 25 февраля 2019

Что могло случиться с вашим разделом Windows, так это то, что выходные JSON-файлы qark были записаны в какой-то важной области на диске, что повредило некоторую структуру данных, такую ​​как MFT (в случае, если вы используете NTFS).

Втвой код ты породил 10 рабочих потоков.Это потоки памяти и интенсивной обработки.Если у вас нет более 10 ядер, это потребит всю вашу вычислительную мощность, вызовет гиперпоточность (если доступно) и сделает систему слишком медленной.

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

with concurrent.futures.ProcessPoolExecutor(max_workers = os.cpu_count()) as executor:

    futuresList = []

                             . . .

Другая проблема заключается в том, что статический анализ, как известно, вызывает проблемы с qark .

Наконец, обратите внимание, что 100 apks - это большойнагрузки.Ожидается, что это займет некоторое время.Если ресурсы перепрошены, условия гонки могут привести к ухудшению производительности, чем если бы было выделено меньше ресурсов.Вы должны настроить свою обработку или даже использование памяти .

...