Internal buffer error memory allocation failed growing buffer

I'm working on a script which scrapes thousands of different web pages. Since these pages are usually different (has different sites), I use multithreading to speed up scraping. EDIT: SIMPLE SHORT

I’m working on a script which scrapes thousands of different web pages. Since these pages are usually different (has different sites), I use multithreading to speed up scraping.

EDIT: SIMPLE SHORT EXPLANATION

——-

I’m loading 300 urls (htmls) in one pool of 300 workers. Since the size of html is variable, sometimes, the sum of sizes is probably too big and python raises: internal buffer error : Memory allocation failed : growing buffer. I want to somehow check if this can happend and if, wait until the buffer is not full.

——-

This approach works but sometimes, python starts to throw:

internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer

into console. I suppose that it is because of size of html I store in memory, which can be 300*(for example 1mb) = 300mb

EDIT:

I know that I can decrease number of workers and I will. But it’s not a solution, there would be just lower chance to get such error. I want to avoid this error at all…

I started to log html sizes:

ram_logger.debug('SIZE: {}'.format(sys.getsizeof(html)))

And the result is (part):

2017-03-05 13:02:04,914 DEBUG SIZE: 243940
2017-03-05 13:02:05,023 DEBUG SIZE: 138384
2017-03-05 13:02:05,026 DEBUG SIZE: 1185964
2017-03-05 13:02:05,141 DEBUG SIZE: 1203715
2017-03-05 13:02:05,213 DEBUG SIZE: 291415
2017-03-05 13:02:05,213 DEBUG SIZE: 287030
2017-03-05 13:02:05,224 DEBUG SIZE: 1192165
2017-03-05 13:02:05,230 DEBUG SIZE: 1193751
2017-03-05 13:02:05,234 DEBUG SIZE: 359193
2017-03-05 13:02:05,247 DEBUG SIZE: 23703
2017-03-05 13:02:05,252 DEBUG SIZE: 24606
2017-03-05 13:02:05,275 DEBUG SIZE: 302388
2017-03-05 13:02:05,329 DEBUG SIZE: 334925

This is my simplified scraping approach:

def scrape_chunk(chunk):
    pool = Pool(300)
    results = pool.map(scrape_chunk_item, chunk)
    pool.close()
    pool.join()
    return results

def scrape_chunk_item(item):
    root_result = _load_root(item.get('url'))
    # parse using xpath and return

And the function to load html:

def _load_root(url):
    for i in xrange(settings.ENGINE_NUMBER_OF_CONNECTION_ATTEMPTS):
        try:
            headers = requests.utils.default_headers()
            headers['User-Agent'] = ua.chrome
            r = requests.get(url, timeout=(settings.ENGINE_SCRAPER_REQUEST_TIMEOUT + i, 10 + i), verify=False, )
            r.raise_for_status()
        except requests.Timeout as e:

            if i >= settings.ENGINE_NUMBER_OF_CONNECTION_ATTEMPTS - 1:
                tb = traceback.format_exc()
                return {'success': False, 'root': None, 'error': 'timeout', 'traceback': tb}
        except Exception:
            tb = traceback.format_exc()
            return {'success': False, 'root': None, 'error': 'unknown_error', 'traceback': tb}
        else:
            break

    r.encoding = 'utf-8'
    html = r.content
    ram_logger.debug('SIZE: {}'.format(sys.getsizeof(html)))
    try:
        root = etree.fromstring(html, etree.HTMLParser())
    except Exception:
        tb = traceback.format_exc()
        return {'success': False, 'root': None, 'error': 'root_error', 'traceback': tb}

    return {'success': True, 'root': root}

Do you know how to make it safe? Something which make workers wait if there would be buffer overflow problem?

Don’t reinvent the wheel and use Scrapy web-scraping framework:

Scrapy is an application framework for crawling web sites and
extracting structured data which can be used for a wide range of
useful applications, like data mining, information processing or
historical archival.

Think about it — the scalability/parallelizing/performance problem is solved for you — do you really want to continue diving into wonderful world of Threads in python, making your code smell suspiciously, hitting the CPU and memory limits, handling conflicts and, at the end, making your code impossible to debug and maintain — instead of focusing on the extracting and collecting the data? And, even with gevent I doubt your final code would be in any ways more simple and readable as the same you would implement based on Scrapy. Why not use the tool that was tested and used by a huge amount of users proven to be the best tool ever created in the web-scraping python world?

Here is a working spider that scrapes the quotes in a similar manner:

from scrapy.spider import Spider
from scrapy.item import Item, Field
from scrapy.http import Request


class BloombergItem(Item):
    ur = Field()
    parameter = Field()
    value = Field()


class BloombergSpider(Spider):
    name = 'bloomberg'
    allowed_domains = ['www.bloomberg.com']

    def start_requests(self):
        with open("stocks.txt") as f:
            for ur in f:
                yield Request("http://www.bloomberg.com/quote/%s:US" % ur)

    def parse(self, response):
        for parameter in response.css('table.key_stat_data tr'):
            item = BloombergItem()
            item['ur'] = response.xpath('//title/text()').extract()[0].split(':')[0]
            item['parameter'] = parameter.xpath('th/text()').extract()[0]
            item['value'] = parameter.xpath('td/text()').extract()[0]
            yield item

If the contents of stocks.txt is:

AAPL

The spider would output (for example, if you would choose to output it in JSON):

[
  {
    "parameter": "Current P/E Ratio (ttm)",
    "value": "16.6091",
    "ur": "AAPL"
  },
  {
    "parameter": "Estimated P/E(09/2015)",
    "value": "13.6668",
    "ur": "AAPL"
  },
  {
    "parameter": "Relative P/E vs.",
    "value": "0.9439",
    "ur": "AAPL"
  },
  ...
]

A good place to start with Scrapy is the Scrapy Tutorial.

За последние 24 часа нас посетил 11621 программист и 1154 робота. Сейчас ищут 216 программистов …


  1. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    В скрипте прописано первой же строчкой:

    1. ini_set(‘memory_limit’, ‘-1’);

    При этом вылетает Out of memory (allocated 14680064) (tried to allocate 11423240 bytes).
    Скрипт расшифровывает xml файлы, т.е. в один момент в переменной находится всё содержимое xml файла, да он бывает иногда большой(от 100мб). Но неужели сервер не выдержит такого? Или может тут есть косяк какой-то? Утечек вроде других нету, все подчищаю, просто файлы сами по себе большие.


  2. Fell-x27

    Команда форума
    Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.162
    Симпатии:
    1.770
    Адрес:
    :сердА

    1) Какая версия пыха?
    2) Сервер ваш?
    3) Профилирование расхода памяти xdebug-ом делали таймстампом?
    4) Имеют место забор/передача данных? Если да, то как? Используется ли буферизация вывода?
    5) Сколько памяти на сервере?


  3. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    1)7.0.20
    2)Да, xampp
    3)Нет, хз, что это, просто через функцию стандартную и вывод проверял какая переменная скок занимает.
    4)Если правильно понял, то данные берутся прямиком из файла, заносятся в mysql. Вывода вообще нету, только в mysql все кладет
    5)Если я правильно понимаю, то поскольку я на локальном, то этот вопрос отпадает?


  4. Fell-x27

    Команда форума
    Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.162
    Симпатии:
    1.770
    Адрес:
    :сердА

    Нет, не отпадает. Нужно поглядеть, во что уперся пых.

    xdebug — библиотека для отладки. Одна из ее фич — возможность профилирования работы приложения от вызова к вызову. В итоге получается текстовый файл, где в каждой строке указан вызов функции какой-либо, время, затраченное на выполнение, изменение расхода памяти, общая память, точка вызова и тд, там настраивается. Ну и время самого приложения в конкретный момент.

    Помогает реально увидеть утечки, а не на предположениях. Вы думаете, что их нет, а они могут быть в самых неожиданных местах. На данный момент пыха ругается, что ей полтора гига не дали откусить. Полтора гига — это что-то запредельное. Не удивлюсь, если там сам апач перегруженный модулями, еще с пол-гига жрет, и вылет происходит из-за упирания в планку «2гб на 32-битный процесс».


  5. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    Вроде я нашел что-то типа утечки (а точнее оптимизировал немного), без xdebug’a, а то у меня что-то не получилось с ним(не отсылает в phpstorm ответку по переменным). Теперь другая проблема, тоже связанная с памятью, мне кажется тут может быть уже сам simpleXML такие объемы не вытягивает?

    1. SimpleXMLElement::__construct(): Memory allocation failed : growing buffer in

    Или это по прежнему утечка где то?

    Раз у меня локальный, то апач же всю оперативку забирает или не? У меня 4гб. Или нет? А как узнать тогда, я не нагуглил что-то)
    Кстати сам файл 150мб весит. Я заметил, что вылетает такая ошибка только на файлах больше ~70мб


  6. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    Вроде разобрался с xdebug’ом, не знаю он ли эту инфу выдал, но вот:
    time memory
    4.2831 167594464 __construct ( ??? ) …class.php:700
    Вот строчка говорит, что памяти много берет. Это конструктор класса simpleXMLElement. То есть утечек нет, тупо такие большие файлы обрабатывать памяти не хватает? Вообще это было бы довольно логично, если файл ~100мб, то объект будет намного больше
    — Добавлено —
    Какой выход тогда?


  7. Fell-x27

    Команда форума
    Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.162
    Симпатии:
    1.770
    Адрес:
    :сердА

    Может быть ограничение памяти на процесс апача. И его нужно повысить.
    Тут есть ответы на эту тему — https://stackoverflow.com/questions/4399138/upper-memory-limit-for-php-apache, мб пригодится. Под топом там как раз про апач.
    — Добавлено —
    Но это, разумеется, не решение проблемы, а отсрочка. Если размер файлов будет расти, все равно упретесь.
    Тут нужно что-то типа lazy_load. Надо поглядеть, умеет ли simpleXML в такое. Если нет, то использовать расширение, которое умеет. Их много у пыхи, что-то да найдется.

    Суть приема lazy load в том, что в память мы грузим не все сразу, а только сигнатуры узлов. Сам же узел грузится в память только при обращении к нему. Причем тоже не весь, а лишь в виде сигнатур узлов и атрибутов, по которым, при обращении можно получить конечные данные или другие узлы. А по завершению работы с ним, его можно выгрузить. Таким макаром можно хоть гигабайтовые структуры ворочать и не упираться ни в какие лимиты.


  8. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    Добавил, как там говорилось строки:

    1. #RLimitMEM 85643200 104857600   # Limit to: 80Mb / process, 100Mb total
    2. RLimitMEM 42949672960 85983232000   # Limit to: 128Mb / Process, 512Mb total

    Ну цифры я побольше сделал) Сейчас они тут нереальные, но я много раз реальные вводил и по итогу толку насколько я понял 0, но я заметил такую вещь: если скрипт не может распарсить один файл(слишком много весит), то сколько я не перезапускай скрипт, ничего, но если апач перезапустить, то он 2-3 распарсивает, а потом опять та же песня, и такая махинация работает вроде как. С чем это может быть связано?
    — Добавлено —
    Про laze load интересно, спасибо, можете посоветовать, где прочитать про это можно и чтобы сразу потом в код вклинить?
    — Добавлено —
    Вообще я думал о том, что тут решило бы проблему не сразу весь файл брать, а по частям, но все реализации мне виделись костыльными, да и щас я совсем ума ни приложу, как это оформить


  9. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    Можете, пожалуйста, подсказать в направление каких методов смотреть? Или в общих чертах как делается такое, дальше я уж сам постараюсь реализовать это


  10. Fell-x27

    Команда форума
    Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.162
    Симпатии:
    1.770
    Адрес:
    :сердА

    Сервер после этого перезапускать надо, к слову.
    — Добавлено —

    Да хоть с блокировкой файла, которая выставлялась от имени апача, а потом пых умирал и не снимал ее. Я хз что у вас там происходит, ищите…

    А никак. XML по частям не прочитать, это же не потоковый формат, как обычный текст. В лоб это не решается чтением по кускам. Там хитрее надо быть.

    Документация по PHP -> библиотеки для работы с XML.


  11. mkramer

    Команда форума
    Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.493
    Симпатии:
    1.732

    XMLReader позволяет сократить расход памяти на чтение XML, но делает это чуть более сложной задачей. Я вот это использовал: https://gist.github.com/justthefish/9302625, мне понравилось


  12. neverlose

    neverlose
    Активный пользователь

    С нами с:
    27 авг 2008
    Сообщения:
    1.112
    Симпатии:
    20

    14680064 bytes = 14336 Kilobytes = 14 Megabytes
    11423240 bytes = ~11156 Kilobytes = ~11 Megabytes


  13. Fell-x27

    Команда форума
    Модератор

    С нами с:
    25 июл 2013
    Сообщения:
    12.162
    Симпатии:
    1.770
    Адрес:
    :сердА

    Да, с полутора гигами я маху дал на два регистра.


  14. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

    Тогда тем более вопрос почему, вылетает при 14 мб, когда без ограничений стоит?) Да и я щас посмотрел, конструктор берет ~150мб примерно, тоже не особо много
    — Добавлено —
    Вообще там структура xml файла повторяющаяся, что то типа такого:

    все равно не получится никаким костылем считать? может как нибудь вызывать определенные строки по очереди


  15. mkramer

    Команда форума
    Модератор

    С нами с:
    20 июн 2012
    Сообщения:
    8.493
    Симпатии:
    1.732

    Я же дал ссылку. Хотя странно, что php ругается на память. Вариант, который я дал, не строит DOM, поэтому использует значительно меньше памяти


  16. Errrrorrrr

    С нами с:
    28 июл 2016
    Сообщения:
    43
    Симпатии:
    0

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

Я работаю над скриптом, который сбрасывает тысячи различных веб-страниц. Поскольку эти страницы обычно разные (имеют разные сайты), я использую многопоточность, чтобы ускорить очистку.

EDIT: ПРОСТОЕ КОРОТКОЕ ПОЯСНЕНИЕ

——-

Я загружаю 300 URL-адресов (htmls) в одном пуле из 300 человек. Так как размер html является переменным, иногда сумма размеров, вероятно, слишком велика и повышает уровень python: internal buffer error: Memory allocation failed: growing buffer. Я хочу как-то проверить, может ли это произойти, и если, подождите, пока буфер не будет заполнен.

——-

Этот подход работает, но иногда питон начинает бросать:

internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer
internal buffer error : Memory allocation failed : growing buffer

в консоль. Я полагаю, что это из-за размера html я храню в памяти, который может быть 300 * (например, 1mb) = 300mb

РЕДАКТИРОВАТЬ:

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

Я начал регистрировать размеры html:

ram_logger.debug('SIZE: {}'.format(sys.getsizeof(html)))

И результат (часть):

2017-03-05 13:02:04,914 DEBUG SIZE: 243940
2017-03-05 13:02:05,023 DEBUG SIZE: 138384
2017-03-05 13:02:05,026 DEBUG SIZE: 1185964
2017-03-05 13:02:05,141 DEBUG SIZE: 1203715
2017-03-05 13:02:05,213 DEBUG SIZE: 291415
2017-03-05 13:02:05,213 DEBUG SIZE: 287030
2017-03-05 13:02:05,224 DEBUG SIZE: 1192165
2017-03-05 13:02:05,230 DEBUG SIZE: 1193751
2017-03-05 13:02:05,234 DEBUG SIZE: 359193
2017-03-05 13:02:05,247 DEBUG SIZE: 23703
2017-03-05 13:02:05,252 DEBUG SIZE: 24606
2017-03-05 13:02:05,275 DEBUG SIZE: 302388
2017-03-05 13:02:05,329 DEBUG SIZE: 334925

Это мой упрощенный метод скремблирования:

def scrape_chunk(chunk):
    pool = Pool(300)
    results = pool.map(scrape_chunk_item, chunk)
    pool.close()
    pool.join()
    return results

def scrape_chunk_item(item):
    root_result = _load_root(item.get('url'))
    # parse using xpath and return

И функция загрузки html:

def _load_root(url):
    for i in xrange(settings.ENGINE_NUMBER_OF_CONNECTION_ATTEMPTS):
        try:
            headers = requests.utils.default_headers()
            headers['User-Agent'] = ua.chrome
            r = requests.get(url, timeout=(settings.ENGINE_SCRAPER_REQUEST_TIMEOUT + i, 10 + i), verify=False, )
            r.raise_for_status()
        except requests.Timeout as e:

            if i >= settings.ENGINE_NUMBER_OF_CONNECTION_ATTEMPTS - 1:
                tb = traceback.format_exc()
                return {'success': False, 'root': None, 'error': 'timeout', 'traceback': tb}
        except Exception:
            tb = traceback.format_exc()
            return {'success': False, 'root': None, 'error': 'unknown_error', 'traceback': tb}
        else:
            break

    r.encoding = 'utf-8'
    html = r.content
    ram_logger.debug('SIZE: {}'.format(sys.getsizeof(html)))
    try:
        root = etree.fromstring(html, etree.HTMLParser())
    except Exception:
        tb = traceback.format_exc()
        return {'success': False, 'root': None, 'error': 'root_error', 'traceback': tb}

    return {'success': True, 'root': root}

Вы знаете, как сделать его безопасным? Что-то, что заставляет рабочих ждать, если проблема с переполнением буфера?

Help

Odoo is the world’s easiest all-in-one management software.
It includes hundreds of business apps:

  • CRM
  • e-Commerce
  • Accounting
  • Inventory
  • PoS
  • Project management
  • MRP

Take the tour

  • All Forums

  • Topics
  • People
  • Tags
  • Badges
  • About

Avatar

Hi Community,

odoo service stopped in server with following error

odoo-bin[9003]: internal buffer error : Memory allocation failed : growing buffer
odoo-bin[9003]: I/O error : buffer full
odoo.service: Main process exited, code=killed, status=11/SEGV
odoo.service: Failed with result 'signal'.

Thanks in Advance

Avatar

No workers are configured

2Answers

Issue might be happening due to some of cron stuck in processing. you can check by putting logger. 

Bug #77212 Memory allocation failed : growing buffer on aws server
Submitted: 2018-11-28 13:09 UTC Modified: 2018-11-28 15:18 UTC
From: sujaljhaonly4u at gmail dot com Assigned:
Status: Not a bug Package: SimpleXML related
PHP Version: 5.6.38 OS: linux
Private report: No CVE-ID: None

 [2018-11-28 13:09 UTC] sujaljhaonly4u at gmail dot com

Description:
------------
Hi, i am receiving this message when i am trying to parse the 1.7gb xml file for inserting on aws server.
Memory allocation failed : growing buffer..
please help me out!

Thank You,

Sujal Jha

Test script:
---------------
<?php
include('../product/upload_function_backup.php');
include('../../config/database.php');
include('../../objects/hooks/function.php');
$dir = '../product_feeds/tata cliq';
$file= "tata_cliq_fashion.xml";
$data = file_get_contents($dir.'/'.$file);
$xml=stripslashes($data);
libxml_use_internal_errors(true);
$arr = simplexml_load_string((string)$xml);
foreach( libxml_get_errors() as $error ) {

    print_r($error);
}
print_r($arr);
?>


Expected result:
----------------
SimpleXMLElement Object
(
    [Product] => Array
        (
            [0] => SimpleXMLElement Object
                (
                    [ProductID] => 1065005367
                    [ProductSKU] => A08160
                    [ProductName] => WOMEN'S TRAINING STELLASPORT WOVEN SHORTS
                    [ProductDescription] => Stella McCartney inspired adidas SC Woven shorts for women. It comes with an Elasticated waist with two side pockets, one back zipped pocket and all-over 'Stellasport' branding.
                    [ProductPrice] => 1000.00
                    [ProductPriceCurrency] => INR
                    [WasPrice] => 2499.00
                    [DiscountedPrice] => 0.00
                    [ProductURL] => http://clk.omgt5.com/?AID=1327881&PID=17736&Type=12&r=https://shop.adidas.co.in/%23!product/A08160_scwovenshort
                    [PID] => 17736
                    [MID] => 929898
                    [ProductImageMediumURL] => https://content.adidas.co.in/static/Product-A08160/Women_Training_Shorts_A08160_1.jpg
                    [StockAvailability] => In stock
                    [Brand] => SPORT PERFORMANCE
                    [custom1] => Gender - Female
                    [custom2] => AgeGroup - Adult
                    [CategoryName] => SHORTS (1/4)
                    [CategoryPathAsString] => Root|TEXTILES|SHORTS (1/4)|
                )
)


Patches

add-fronk-support
(last revision 2018-11-28 13:15 UTC by sujaljhaonly4u at gmail dot com)

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports

 [2018-11-28 14:19 UTC] spam2 at rhsoft dot net

this is a bugtracker and not a support forum!

contact your administrator and make sure you have *at least* twice the memory of stuff you want to proceed available and that there are no resource limits

 [2018-11-28 15:18 UTC] cmb@php.net

-Status: Open
+Status: Not a bug

 [2018-11-28 15:18 UTC] cmb@php.net

Sorry, but your problem does not imply a bug in PHP itself.  For a
list of more appropriate places to ask for help using PHP, please
visit http://www.php.net/support.php as this bug system is not the
appropriate forum for asking support questions.  Due to the volume
of reports we can not explain in detail here why your report is not
a bug.  The support channels will be able to provide an explanation
for you.

Thank you for your interest in PHP.

Понравилась статья? Поделить с друзьями:
  • Internal auth provider error mcskill
  • Intel haxm error
  • Intel graphics experience ошибка
  • Intel flash programming tool error 201
  • Intel extreme tuning utility ошибка при установке