Устранение неполадок герою "Ошибка R14 (превышена квота памяти)" в приложении plotly dash - PullRequest
0 голосов
/ 23 апреля 2019

Я работаю над героем, который рассчитывает статистику по изображению, загруженному пользователем.Предполагается, что изображения представляют собой png-файлы с пикселями, помеченными в соответствии с классами, связанными со значениями rgb.Моя проблема в том, что изображения очень большие (около 10k x 10k пикселей, ~ 3 МБ), и я превышаю квоту памяти на heroku.При локальном тестировании это медленно, но функционально.Я новичок в веб-программировании и не совсем уверен, как решить эту проблему.

Я нашел этот пример https://github.com/plotly/dash-image-processing и протестировал его с большими изображениями на моем аккаунте heroku.Это сработало, но я немного растерялся, пытаясь понять код, и функциональность в любом случае разная (я использую Pillow, чтобы преобразовать изображение rgb в оттенки серого, а затем подсчитать процент пикселей, соответствующий данному классу).Вот функция обратного вызова, в которой выполняются вычисления.

@app.callback(
    Output('output-species-count', 'children'),
    [Input('upload-image', 'contents')]
)
def species_count(images):

    if not images:
        return
    else:

        t_start = time.time()

        for image_str in images:

            # Convert contents to I/O buffer
            image = image_str.split(',')[-1]
            string = image.split(';base64,')[-1]
            decoded = base64.b64decode(string)
            buffer = BytesIO(decoded)

            # Read buffer as grayscale PIL image, then convert to numpy array
            im = np.array(Image.open(buffer).convert('L'))

            # Count number of pixels per species
            counts_dict = dict(zip(legend.keys(), [0] * len(legend)))
            for k in legend.keys():
                counts_dict[k] =  len(np.where(im == legend[k]['gray'])[0])

            # List the counts to pass to "values" below for percents calculation
            counts_list = list(counts_dict.values())

            t_end = time.time()
            if DEBUG:
                print(f"Calculated percent cover in {t_end - t_start:.3f} sec")

            children = [
                html.Div([
                    dcc.Graph(
                            figure={
                                "data": [
                                    {
                                        "type": "pie",
                                        "hoverinfo": "label+percent",
                                        "labels": list(counts_dict.keys()),
                                        "values": counts_list,
                                        "marker": {
                                            "colors": [
                                                'rgb'+str(tuple(v['rgb'])) 
                                                for k, v in legend.items()
                                            ]
                                        },
                                        "hole": 0.4
                                    }
                                ],
                                "layout": {
                                    "title": "Species Percent Cover"
                                }
                            }
                    )
                ])
            ]

        return children

Я обрезал одно из больших (13k x 13k) изображений до 2k, 4k, 6k, 8k и 10k, и оно было выполнено в 0,5, 3,5, 6,0и 17,5 секунд, но разбился на 10к.Вот журнал Heroku:

2019-04-23T14:42:12.508428+00:00 heroku[router]: at=info method=POST path="/_dash-update-component" host=coral-stats.herokuapp.com request_id=aca53727-2642-43bb-903f-6c99745efd36 fwd="152.20.237.233" dyno=web.1 connect=1ms service=465ms status=200 bytes=1218050 protocol=https
2019-04-23T14:42:12.496310+00:00 app[web.1]: 10.30.78.6 - - [23/Apr/2019:14:42:12 +0000] "POST /_dash-update-component HTTP/1.1" 200 1217846 "https://coral-stats.herokuapp.com/" "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.103 Safari/537.36"
2019-04-23T14:42:22.977433+00:00 heroku[web.1]: State changed from crashed to starting
2019-04-23T14:42:22.972132+00:00 heroku[web.1]: State changed from up to crashed
2019-04-23T14:42:22.812554+00:00 heroku[web.1]: source=web.1 dyno=heroku.125670006.f31289d1-cba6-4ec7-a802-176bc0e5e051 sample#load_avg_1m=0.21 sample#load_avg_5m=0.11 sample#load_avg_15m=0.04
2019-04-23T14:42:22.812643+00:00 heroku[web.1]: source=web.1 dyno=heroku.125670006.f31289d1-cba6-4ec7-a802-176bc0e5e051 sample#memory_total=1025.27MB sample#memory_rss=511.96MB sample#memory_cache=0.00MB sample#memory_swap=513.30MB sample#memory_pgpgin=988792pages sample#memory_pgpgout=858752pages sample#memory_quota=512.00MB
2019-04-23T14:42:22.813151+00:00 heroku[web.1]: Process running mem=1027M(200.7%)
2019-04-23T14:42:22.813235+00:00 heroku[web.1]: Error R15 (Memory quota vastly exceeded)
2019-04-23T14:42:22.813316+00:00 heroku[web.1]: Stopping process with SIGKILL
2019-04-23T14:42:22.959604+00:00 heroku[web.1]: Process exited with status 137
2019-04-23T14:42:22.901815+00:00 heroku[router]: at=error code=H13 desc="Connection closed without response" method=POST path="/_dash-update-component" host=coral-stats.herokuapp.com request_id=861e4582-924d-4f53-9137-b56e8e55b345 fwd="152.20.237.233" dyno=web.1 connect=1ms service=10902ms status=503 bytes=0 protocol=https

Я также отображаю изображение в браузере в виде эскиза.Так у меня основная проблема с кэшированием или хранением?

...