Possible memory leak after a high number of transcriptions
donand opened this issue · comments
Describe the bug
When I generate a high number of transcriptions with the espeak-ng backend of single sentences inside Flask, the time taken by the transcription grows from 150 ms to 2000 ms and after around 2100 requests it starts giving always an error.
The error is one of the following two
OSError: /tmp/tmpd_vs36iz/libespeak-ng.so.1.1.51: failed to map segment from shared object
OSError: /tmp/tmp4ntbh189/libespeak-ng.so.1.1.51: cannot change memory protections
By removing the phonemizer package and calling directly espeak-ng with subprocess the issue is solved. The same if I call phonemizer with subprocess, but is much slower than calling it from python (500 ms vs 150 ms).
Phonemizer version
phonemizer-3.0
available backends: espeak-ng-1.51, segments-2.2.0
uninstalled backends: espeak-mbrola, festival
System
Distributor ID: Ubuntu
Description: Ubuntu 20.04.2 LTS
Release: 20.04
Codename: focal
To reproduce
Have a Flask web app with a Waitress server that calls the phonemizer.phonemize() function around 2100 times.
Expected behavior
The transcription time should stay the same and not increase, and it should not give that error.
Additional context
I'm using the phonemizer as a python package, imported from a Flask web application with the Waitress server.
Hi, I think this is probably caused by the number of EspeakBackend
classes you instantiate (one per call to phonemize
). See https://github.com/bootphon/phonemizer#advice-for-best-performances.
You should instantiate once, then call phonemize
from here:
from phonemizer.backend import EspeakBackend
backend = EspeakBackend('en-us', ...)
phonemized = [backend.phonemize(line, ...) for line in flask_requests]
The bug is probably caused by the way espeak
library is binded to Python here
But... well... This is definitely a bug. We should at least catch the OSError
and re-raise a more explicit error message.
Thank you for the info! I definitely missed that part of the separate instantiation of the Espeak backend. I will try to replace the calls to the phonemize function with the calls to the backend and run a test.
Note: I'll add a documentation section (somewhere) to document this usage of the lib (i've had to do the same thing about 4 months ago).
Got hit by that too! The documentation section about how to reduce the memory footprint of the phonemizer when used eg in a loop is here : https://bootphon.github.io/phonemizer/common_issues.html#phonemization-is-slow.
Maybe it could be worth mentionning this on the usage page (for use in a loop avoid calling phonemize(text, ...)
directly but use backend.phonemize(line, ...)
on a properly initialized backend (see https://bootphon.github.io/phonemizer/common_issues.html#phonemization-is-slow for more details).
Got hit by that too! The documentation section about how to reduce the memory footprint of the phonemizer when used eg in a loop is here : bootphon.github.io/phonemizer/common_issues.html#phonemization-is-slow.
Maybe it could be worth mentionning this on the usage page (for use in a loop avoid calling
phonemize(text, ...)
directly but usebackend.phonemize(line, ...)
on a properly initialized backend (see bootphon.github.io/phonemizer/common_issues.html#phonemization-is-slow for more details).
The backend phonemize
method does not have the preserve_punctuation
option. Apart from handling the punctuations separately outside, is there something inbuilt that I'm missing?
It has, in the class constructor:
from phonemizer.backend import EspeakBackend
backend = EspeakBackend('en-us', preserve_punctuation=True, other options...)
phonemized = [backend.phonemize(line, ...) for line in text]