Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Zagursky

844 views

Published on

  • Be the first to comment

  • Be the first to like this

Zagursky

  1. 1. ФайберыНевытесняющая многозадачность на Java
  2. 2. public final class RequestCreateAvatar { private final String avatarName;} S private final Character character; Rvoid createAvatar(String avatarName, Character character) { MsgRequest sendCmd(new RequestCreateAvatar(avatarName, character)); Async<Void> createAvatar(String avatarName, Character character) {} CreateAvatarResult result = call(avatarManager.createAvatar( avatarName, characterfinal class CreateAvatarHandler { public )); RequestHandler() public void handle(RequestCreateAvatar msg) { sendMsgToClient(result); CreateAvatarResult result = avatarManager.createAvatar(msg); sendMsg(new ResponseCreateAvatar(result)); MsgResponse return nothing(); } } }public final class CreateAvatarResponseHandler { public void handle(ResponseCreateAvatar msg) { sendMsgToClient(msg); ResponseHandler() }}
  3. 3. Причины• Хочется писать простой линейный Java-код• ОС-потоки слишком накладны• Требуется сохранить однопоточный дизайн
  4. 4. С высоты птичьего полётаИнструментатор Планировщик Рантайм Инспекции
  5. 5. Синтаксис (1) import fibers.Async; import static fibers.Fiber.*;Async<Integer>{ calcResult(int factor) { class Foo Async<Integer> calcResult(int factor) { return result(42*factor); return result(42*factor);Async<Integer> doWork() {} } int tmp Async<Integer> doWork() { = сall(calcResult(314)); int tmp = call(calcResult(314)); return result(tmp); return result(tmp);} } }
  6. 6. Синтаксис (2)class Foo { void bar(FiberManager f) { f.scheduleFiber(doWork("Hi!")); }}
  7. 7. Препарируемый методAsync<String> baz(String second) { String first = call(getFirst()); return result(join(first, second));}
  8. 8. Замена исходного методаAsync<String> baz(String second) { return new baz_Context(second);}
  9. 9. Контекст вызова методаclass baz_Context extends Async<String> { String _second, first; @Override void update() { state = baz_Async(this); }}
  10. 10. Инструментированный методint baz_Async(baz_Context c) { switch (c.state) { case 0: c.result = getFirst(); return 1; case 1: c.first = (String) c.takeResult(); c.result = join(c.first, c._second); return -1; }}
  11. 11. Инструментирование (1)• Поиск точек разрыва – call – yield• Вставка switch-case и return
  12. 12. Инструментирование (2)• Как обойти вызов Async<Integer> foo() { блока finally? try { int t = call(bar());• Не вызывать его! return result(t); } finally { close(); } }
  13. 13. Инструментирование (3)• Подмена доступа к параметрам метода и локальным переменным• int x; x = 42;  context.x = 42;
  14. 14. Инструментирование (4) ... case 42... Context r = new bar_Context();x = call(bar()); c.pushCall(r);... return 43; case 43: c.x = (String) c.takeResult(); ...
  15. 15. Инструментирование (5)• Директивы, ссылающиеся на исходный файл, вставляются инструментатором в сгенерированный метод• Это позволяет использовать пошаговую отладку• Ограничение: нельзя с помощью Step Over перейти через точку разрыва
  16. 16. Исключения• Рантайм ловит все исключения, вылетевшие из Async-метода• Исключение заворачивается в служебный объект• При запросе результата вызывающим Async- методом исключение выбрасывается заново• Если исключение вылетает за пределы файбера, то это диагностируется как ошибка
  17. 17. Прерывание файбера• В каждой точке входа в Async-метод проверяется, не был ли прерван текущий файбер• Если файбер был прерван, то выбрасывается служебное исключение FiberInterruptedException
  18. 18. Функции FiberManager• Планировщик• Обрабатывает приостановку, возобновление и прерывание файберов• У всех файберов одинаковый приоритет
  19. 19. Гарантии FiberManager• Файберы должны исполняться в порядке добавления и возобновления• Приостановленные файберы не должны исполняться
  20. 20. Thread safety• Методы scheduleFiber() и resumeFiber() могут выполняться из любого потока• Все остальные методы – только из потока, к которому привязан планировщик• На каждый поток есть свой планировщик
  21. 21. StackTrace (1)• Stack trace из new Throwable().getStackTrace() не достаточен• Программист хочет видеть: – стек Async-методов – стек в момент порождения файбера• Файбер может быть создан внутри другого файбера• Stack trace должен разрешаться (resolve) только тогда, когда он реально необходим
  22. 22. StackTrace (2)• Рантайм получает уже готовое исключение• К этому исключению нужно добавить – стек файбера – стек момента порождения файбера• Используется addSuppressed()
  23. 23. StackTrace (3)• Переопределяется метод fillInStackTrace(), чтобы не собирать обычный stack trace• Массив StackTraceElement[] формируется только по запросу getCause() и при сериализации
  24. 24. java.lang.Throwable at asserts.Verify.fail(Verify.java:47) at gm.cc.c.t.CmdTeleportRandomByMapType.asyncRun$Async(CmdTeleportRandomByMapType.jav at gm.cc.c.t.CmdTeleportRandomByMapType$Context_asyncRun_LmsgSystem#locales#Abonent_. at f.i.AsyncImpl.updateSafe(AsyncImpl.java:37) at f.i.FiberImpl.updateInternal(FiberImpl.java:154) at f.i.FiberImpl.update(FiberImpl.java:130) at f.i.FiberManagerAbstract.updateFiber(FiberManagerAbstract.java:297) ... at java.lang.Thread.run(Thread.java:722) Suppressed: f.i.FiberStackTraceHolderException: Fiber stack trace Caused by: f.i.FiberStackTraceHolderException$Helper at asserts.Verify.fail(Verify.java:47) at gm.cc.c.t.CmdTeleportRandomByMapType.asyncRun(CmdTeleportRandomByMapType.java at ms.l.AsyncMsg.run(AsyncMsg.java:37) at ms.i.mp.ServerMsgPublisher.processMsg(ServerMsgPublisher.java:331) at ms.i.mp.ServerMsgPublisher.addMsgFast(ServerMsgPublisher.java:118) ... at java.lang.Thread.run(Thread.java:722)
  25. 25. Узкие места (1)• Инструментатор меняет сигнатуру метода• Служебные методы call() и result() вырезаются, чтобы байткод соответствовал новой сигнатуре• Об этом не догадывается IntelliJ Idea, которая вставляет проверки на != null• Инструментатор вырезает такие проверки из Async-методов
  26. 26. Узкие места (2)• Если Async-метод декларирует throws SomeUncheckedException – синтаксис java потребует его обработки – catch-блок для этого исключения никогда не будет вызван – исключение пролетит в рантайм, т. к. для него нет соответствующего catch
  27. 27. Узкие места (3)• Синтаксис не запрещает вызов Async- метода из обычного• Вызываемый метод не исполнится
  28. 28. Узкие места (4)• Точки разрыва не могут быть в блоке finally• Причина: в этом случае исключение может быть проигнорировано
  29. 29. Альтернативные решения• Apache Javaflow• DaVinci VM• Kilim
  30. 30. С е р ге й З а г ур с к и йв е д у щ и й п р о г р а м м и с т, п р о е к т S k y f o r g e s.zagurskiy@corp.mail.ru

×