Что может Python сделать за секунду?

1 / 10

Первая программа, чтобы вы вошли во вкус: сколько проходов по циклу можно совершить за одну секунду?

 
#!/usr/bin/env python

def f(NUMBER):
    for _ in xrange(NUMBER):
        pass

import sys
f(int(sys.argv[1]))
Не верно!

Такой простой цикл пройдёт 68 млн итераций за секунду.


Не верно!

Такой простой цикл пройдёт 68 млн итераций за секунду.


Не верно!

Такой простой цикл пройдёт 68 млн итераций за секунду.


Не верно!

Такой простой цикл пройдёт 68 млн итераций за секунду.


Верно!

Такой простой цикл пройдёт 68 млн итераций за секунду.


Отлично, а теперь попробуйте угадать, сколько записей можно добавить в словарь за секунду.

 
#!/usr/bin/env python

# Мы используем `i % 1000` для контроля
# размера словаря

def f(NUMBER):
    d = {}
    for i in xrange(NUMBER):
        d[i % 1000] = i

import sys
f(int(sys.argv[1]))
Не верно!

За секунду в словарь можно поместить целых 11 млн записей.


Не верно!

За секунду в словарь можно поместить целых 11 млн записей.


Не верно!

За секунду в словарь можно поместить целых 11 млн записей.


Не верно!

За секунду в словарь можно поместить целых 11 млн записей.


Верно!

За секунду в словарь можно поместить целых 11 млн записей.


Мы более-менее разобрались, чего ожидать от Python в лучшем случае, поэтому рассмотрим более реалистичный пример. Как думаете, сколько HTTP-запросов мы пропарсим за секунду?

 
#!/usr/bin/env python

from BaseHTTPServer import BaseHTTPRequestHandler
from StringIO import StringIO

class HTTPRequest(BaseHTTPRequestHandler):
    def __init__(self, request_text):
        self.rfile = StringIO(request_text)
        self.raw_requestline = self.rfile.readline()
        self.error_code = self.error_message = None
        self.parse_request()

    def send_error(self, code, message):
        self.error_code = code
        self.error_message = message

request_text = """GET / HTTP/1.1
Host: localhost:8001
Connection: keep-alive
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.85 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: en-GB,en-US;q=0.8,en;q=0.6
"""

def f(NUMBER):
    for _ in range(NUMBER):
        HTTPRequest(request_text)

import sys
f(int(sys.argv[1]))
Не верно!

За секунду можно пропарсить целых 25 тыс. запросов!


Не верно!

За секунду можно пропарсить целых 25 тыс. запросов!


Верно!

За секунду можно пропарсить целых 25 тыс. запросов!


Не верно!

За секунду можно пропарсить целых 25 тыс. запросов!


Идём дальше. Сколько байт можно записать на SSD-диск за секунду?

 
#!/usr/bin/env python

import tempfile
import os

CHUNK_SIZE = 1000000
s = "a" * CHUNK_SIZE

def cleanup(f, name):
    f.flush()
    os.fsync(f.fileno())
    f.close()
    try:
        os.remove(name)
    except:
        pass

def f(NUMBER):
    name = './out'
    f = open(name, 'w')
    bytes_written = 0
    while bytes_written < NUMBER:
        f.write(s)
        bytes_written += CHUNK_SIZE
    cleanup(f, name)

import sys
f(int(sys.argv[1]))
Не верно!

Правильный ответ — 342 млн байт в секунду.


Не верно!

Правильный ответ — 342 млн байт в секунду.


Не верно!

Правильный ответ — 342 млн байт в секунду.


Верно!

Правильный ответ — 342 млн байт в секунду.


Не верно!

Правильный ответ — 342 млн байт в секунду.


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

 
#!/usr/bin/env python

import cStringIO

CHUNK_SIZE = 1000000
s = "a" * CHUNK_SIZE

def f(NUMBER):
    output = cStringIO.StringIO()
    bytes_written = 0
    while bytes_written < NUMBER:
        output.write(s)
        bytes_written += CHUNK_SIZE

import sys
f(int(sys.argv[1]))
Не верно!

В память можно записывать на скорости 2 млрд байт/секунду. Так что даже с «быстрым» SSD с памятью тягаться пока что рано.


Не верно!

В память можно записывать на скорости 2 млрд байт/секунду. Так что даже с «быстрым» SSD с памятью тягаться пока что рано.


Не верно!

В память можно записывать на скорости 2 млрд байт/секунду. Так что даже с «быстрым» SSD с памятью тягаться пока что рано.


Верно!

В память можно записывать на скорости 2 млрд байт/секунду. Так что даже с «быстрым» SSD с памятью тягаться пока что рано.


А теперь немного баз данных. Допустим у нас есть 2 базы SQLite на 10 млн записей: одна с индексом, другая без. Как думаете, сколько раз в секунду мы можем извлечь запись из базы без индекса?

 
#!/usr/bin/env python

import sqlite3

conn = sqlite3.connect('./unindexed_db.sqlite')
c = conn.cursor()
def f(NUMBER):
    query = "select * from my_table where key = %d" % 5
    for i in xrange(NUMBER):
        c.execute(query)
        c.fetchall()

import sys
f(int(sys.argv[1]))
Верно!

2 запроса в секунду.


Не верно!

2 запроса в секунду.


Не верно!

2 запроса в секунду.


Не верно!

2 запроса в секунду.


Не верно!

2 запроса в секунду.


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

 
#!/usr/bin/env python

import sqlite3

conn = sqlite3.connect('./indexed_db.sqlite')
c = conn.cursor()
def f(NUMBER):
    query = "select * from my_table where key = %d" % 5
    for i in xrange(NUMBER):
        c.execute(query)
        c.fetchall()

import sys
f(int(sys.argv[1]))
Не верно!

Правильный ответ — 53 тыс. запросов в секунду.


Не верно!

Правильный ответ — 53 тыс. запросов в секунду.


Не верно!

Правильный ответ — 53 тыс. запросов в секунду.


Верно!

Правильный ответ — 53 тыс. запросов в секунду.


Перейдём к хешированию. Сначала давайте подумаем, сколько паролей в секунду можно зашифровать с помощью сторонней библиотеки bcrypt?

 
#!/usr/bin/env python

import bcrypt

password = 'a' * 100

def f(NUMBER):
    for _ in xrange(NUMBER):
        bcrypt.hashpw(password, bcrypt.gensalt())

import sys
f(int(sys.argv[1]))
Верно!

С bcrypt можно захешировать всего 3 пароля за секунду. Маловато, не находите?


Не верно!

С bcrypt можно захешировать всего 3 пароля за секунду. Маловато, не находите?


Не верно!

С bcrypt можно захешировать всего 3 пароля за секунду. Маловато, не находите?


Не верно!

С bcrypt можно захешировать всего 3 пароля за секунду. Маловато, не находите?


Не верно!

С bcrypt можно захешировать всего 3 пароля за секунду. Маловато, не находите?


А теперь скажите, сколько байт можно захешировать за секунду, используя md5 из стандартной библиотеки hashlib?

 
#!/usr/bin/env python

import hashlib

CHUNK_SIZE = 10000
s = 'a' * CHUNK_SIZE

def f(NUMBER):
    bytes_hashed = 0
    h = hashlib.md5()
    while bytes_hashed < NUMBER:
        h.update(s)
        bytes_hashed += CHUNK_SIZE
    h.digest()
import sys
f(int(sys.argv[1]))
Не верно!

Правильный ответ — 455 млн. Впечатляющее число, правда?


Не верно!

Правильный ответ — 455 млн. Впечатляющее число, правда?


Не верно!

Правильный ответ — 455 млн. Впечатляющее число, правда?


Не верно!

Правильный ответ — 455 млн. Впечатляющее число, правда?


Верно!

Правильный ответ — 455 млн. Впечатляющее число, правда?


Ну и напоследок немного сериализации. Как известно, на неё можно потратить много времени, особенно при постоянной (де)сериализации одних и тех же данных. Как думаете, сколько раз за секунду можно пропарсить 64 КБ JSON?

 
#!/usr/bin/env python

import json

with open('./setup/protobuf/message.json') as f:
    message = f.read()

def f(NUMBER):
    for _ in xrange(NUMBER):
        json.loads(message)

import sys
f(int(sys.argv[1]))
Не верно!

Цикл пройдёт 449 итераций.


Верно!

Цикл пройдёт 449 итераций.


Не верно!

Цикл пройдёт 449 итераций.


Не верно!

Цикл пройдёт 449 итераций.


Не верно!

Цикл пройдёт 449 итераций.


Далее
0 из 10

Поздравляем с прохождением теста! У вас уже есть некоторые знания о Python, но ещё есть куда расти. Отличное место, где можно подтянуть базу по языку и связать свои навыки с другими современными технологиями – наш сайт PythonTurbo.

Интересно, хочу посмотреть