Первая программа, чтобы вы вошли во вкус: сколько проходов по циклу можно совершить за одну секунду?
#!/usr/bin/env python
def f(NUMBER):
for _ in xrange(NUMBER):
pass
import sys
f(int(sys.argv[1]))
Отлично, а теперь попробуйте угадать, сколько записей можно добавить в словарь за секунду.
#!/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]))
Мы более-менее разобрались, чего ожидать от 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]))
Идём дальше. Сколько байт можно записать на 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]))
А теперь попытайтесь угадать, сколько байт за секунду можно записать в строку в памяти.
#!/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 базы 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]))
А сколько, по-вашему, раз за секунду получится извлечь запись из базы такого же размера, но с индексом?
#!/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]))
Перейдём к хешированию. Сначала давайте подумаем, сколько паролей в секунду можно зашифровать с помощью сторонней библиотеки 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]))
А теперь скажите, сколько байт можно захешировать за секунду, используя 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]))
Ну и напоследок немного сериализации. Как известно, на неё можно потратить много времени, особенно при постоянной (де)сериализации одних и тех же данных. Как думаете, сколько раз за секунду можно пропарсить 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]))
Поздравляем с прохождением теста! У вас уже есть некоторые знания о Python, но ещё есть куда расти. Отличное место, где можно подтянуть базу по языку и связать свои навыки с другими современными технологиями – наш сайт PythonTurbo.