Корутинги должны иметь возможность
Итак, вот небольшая демонстрация асинхронных функций (ака родных сопрограмм), которые делают это без использования asyncio
или любых других модулей / фреймворков, которые обеспечивают цикл событий. Требуется хотя бы python 3.5. См. Комментарии внутри кода.
#!/usr/bin/env python
import types
# two simple async functions
async def outer_af(x):
print("- start outer_af({})".format(x))
val = await inner_af(x) # Normal way to call native coroutine.
# Without `await` keyword it wouldn't
# actually start
print("- inner_af result: {}".format(val))
return "outer_af_result"
async def inner_af(x):
print("-- start inner_af({})".format(x))
val = await receiver() # 'await' can be used not only with native
# coroutines, but also with `generator-based`
# coroutines!
print("-- received val {}".format(val))
return "inner_af_result"
# To yiled execution control to caller it's necessary to use
# 'generator-based' coroutine: the one created with types.coroutine
# decorator
@types.coroutine
def receiver():
print("--- start receiver")
# suspend execution / yield control / communicate with caller
r = yield "value request"
print("--- receiver received {}".format(r))
return r
def main():
# We want to call 'outer_af' async function (aka native coroutine)
# 'await' keyword can't be used here!
# It can only be used inside another async function.
print("*** test started")
c = outer_af(42) # just prepare coroutine object. It's not running yet.
print("*** c is {}".format(c))
# To start coroutine execution call 'send' method.
w = c.send(None) # The first call must have argument None
# Execution of coroutine is now suspended. Execution point is on
# the 'yield' statement inside the 'receiver' coroutine.
# It is waiting for another 'send' method to continue.
# The yielded value can give us a hint about what exectly coroutine
# expects to receive from us.
print("*** w = {}".format(w))
# After next 'send' the coroutines execution would finish.
# Even though the native coroutine object is not iterable it will
# throw StopIteration exception on exit!
try:
w = c.send(25)
# w here would not get any value. This is unreachable.
except StopIteration as e:
print("*** outer_af finished. It returned: {}".format(e.value))
if __name__ == '__main__':
main()
Вывод выглядит так:
*** test started
*** c is <coroutine object outer_af at 0x7f4879188620>
- start outer_af(42)
-- start inner_af(42)
--- start receiver
*** w = value request
--- receiver received 25
-- received val 25
- inner_af result: inner_af_result
*** outer_af finished. It returned: outer_af_result
Дополнительный комментарий. Похоже, что невозможно получить контроль изнутри собственной сопрограммы. yield
не разрешено внутри функций async
! Поэтому необходимо import types
и использовать декоратор coroutine
. Это черная магия! Честно говоря, я не понимаю, почему yield
запрещен, поэтому требуется сборка сопрограмм на основе родных и генераторов.
Сама по себе JVM не будет использовать преимущества специальных функций ЦП при выполнении кода, который является шифрованием AES: распознавание некоторого кода как реализации AES выходит за рамки возможностей JIT-компилятора. Чтобы использовать специальное оборудование (например, «Замок» на процессорах VIA или инструкции AES-NI на новых процессорах Intel), вы должны в какой-то момент пройти через «собственный код».
Возможно, провайдер JCE может сделать это за вас. Я не знаю ни одного легкодоступного поставщика JCE, который включает в себя оптимизированный собственный код для AES (был проект под названием Apache JuiCE , но, похоже, он остановился, и я не знаю его статуса). Однако вполне возможно, что SunJCE сделает это в будущей версии (но с учетом того, что Oracle покупает Sun и слишком много возможностей OpenJDK 7, неясно, когда будет выпущена следующая версия Java). В качестве альтернативы вы можете использовать собственный код самостоятельно. Собственный код вызывается через JNI , а для собственного кода AES популярной реализацией является реализация Брайана Гладмана . Когда вы получаете более крупный и новый процессор с инструкцией AES-NI, замените этот собственный код некоторым кодом, который знает об этих инструкциях, как Intel описывает .
Используя AES-128 вместо AES-256, вы должны получить прирост скорости на + 40%. Взлом AES-128 в настоящее время находится за пределами технологической досягаемости человечества и останется таковой в течение следующих нескольких десятилетий.Вам действительно нужен 256-битный ключ для AES?
Обычно шагом, который использует больше времени, является Инициирование KeyGenerator.
KeyGenerator keyGen = KeyGenerator.getInstance("AES");
keyGen.init(256); // This step takes more time
KeyGenerator aesKey = keyGen.generateKey();
способ, которым я решил его, путем генерации пула KeyGenerator
экземпляры перед сервером statup и многократного использования их для только для Генерации ключей
Я бы также посоветовал использовать AES-128, а не 256. Если код слабо связан и все еще существует, сколько бы лет ни потребовалось для того, чтобы AES-128 стал архаичным, я предполагаю, что его будет намного проще обновить шифрование в этот момент (когда оборудование станет более мощным), чем пытаться оптимизировать производительность с помощью оборудования сейчас.
Конечно, предполагается, что он слабосвязанный: D
Простой поиск в Google выявит несколько поставщиков JCE, которые заявляют об аппаратном ускорении Solaris Crypto Framework. Я слышал, что точка безубыточности составляет 4K (где меньше 4k быстрее выполнять, используя JVM java-провайдеры).
Я мог бы посмотреть на использование реализации NSS, она может иметь некоторые оптимизации компилятора для вашей платформы (и вы, конечно, можете собирать из исходников с их включением); хотя я сам не использовал ее. Большим преимуществом аппаратного провайдера, вероятно, является тот факт, что ключи могут храниться в аппаратном обеспечении таким образом, что их можно использовать, не раскрывая их для ОС.
Обновление: Я должен упомянуть, что в исходнике Keyczar есть полезные сведения (где-то в исходнике или в сопутствующих документах) о снижении накладных расходов на инициализацию шифра. Он также делает именно то, что вы хотите (см. Encrypter), и, похоже, реализует асинхронное шифрование (используя пул потоков).