2017-01-22 8 views
2

У меня есть веб-сервис, который дает мне ОГРОМНЫЙ ответ json. Здесь я предоставляю фрагмент кода iPython.Почему встроенный JSON-застройщик работает быстрее по сравнению с явным загрузчиком JSON?

In [1]: import requests 

In [2]: r = requests.post("<API endpoint>", data={"number_of_row" : 10000000}) 

In [3]: r 
Out[3]: <Response [200]> 

In [4]: import json 

In [5]: %timeit json.loads(r.text) 
1 loop, best of 3: 36.5 s per loop 

In [6]: %timeit r.json() 
10 loops, best of 3: 121 ms per loop 

Сывороточный протеин # 5 занимает столько времени, что линия № 6? В конечном счете, я хочу, чтобы объект JSON не был получен из полученных откликов.

Редактировать # 1: Добавление статистики с помощью simplejson и пост-реверсирование разбора.

In [11]: r = requests.post("<API endpoint>", data={"number_of_row": 10000000}) 

In [12]: res = requests.post("<API endppoint>", data={"number_of_row": 10000000}) 

In [13]: %timeit r.json() 
10 loops, best of 3: 120 ms per loop 

In [14]: %timeit res.json() 
10 loops, best of 3: 120 ms per loop 

In [15]: %timeit json.loads(r.text) 
1 loop, best of 3: 36.5 s per loop 

In [16]: %timeit simplejson.loads(r.text) 
1 loop, best of 3: 36.3 s per loop 

И одна вещь, чтобы отметить, что нет caching реализован в любом месте. Конечные точки API находятся под моим контролем.

Edit # 2:

In [18]: %timeit json.loads(r.content.decode(requests.utils.guess_json_utf(r.content))) 
10 loops, best of 3: 119 ms per loop 

In [19]: %timeit r.json() 
10 loops, best of 3: 63.3 ms per loop 

In [20]: %timeit json.loads(r.text) 
1 loop, best of 3: 36.5 s per loop 

ответ

0

requests.models.Response.json() использует json.loads (или simplejson.loads) interally. Поэтому не должно быть разницы, если вы не установили simplejson.

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

Если вы измените порядок вызовов, вы получите обратный результат.

EDIT

request.models.Response.text использует chardet.detect угадать кодировку ответа, в то время как requests.models.Response.json() использует requests.utils.guess_json_utf, которые только считают utf-8, utf-16, utf-32 в соответствии с JSON RFC 4627 Раздел 3.

In [1]: content = 'a' * 1000000000 

In [2]: import chardet 

In [3]: %timeit chardet.detect(content)['encoding'] 
1 loops, best of 3: 9.6 s per loop 

In [4]: import requests.utils 

In [5]: %timeit requests.utils.guess_json_utf(content) 
1000000 loops, best of 3: 835 ns per loop 
+0

Сомневаюсь n/w IO. Причина, когда я разбираю ответ, n/w IO уже завершен. Это чистая логика синтаксического анализа. Кроме того, я отредактировал свой вопрос с помощью обратных методов парсинга, пожалуйста, проверьте. –

+0

@AashishP, Странно. BTW, кеширование, которое я имел в виду в 'запросах', а не на стороне сервера. – falsetru

+0

@AashishP, не могли бы вы timeit 'json.loads (r.content.decode (запросы.utils.guess_json_utf (r.content)))'? 'Response.text' пытается обнаружить кодировку с помощью' chardet', которые рассматривают все возможные кодировки, а 'Response.json' использует' guess_json_utf', которые рассматривают только utf-8, utf-16, utf-32. – falsetru