Slide 1

Slide 1 text

զʑ͸Ͳ͏΍ͬͯݴޠΛ࡞Γ ൴Β͸Ͳ͏΍ͬͯݴޠΛ๰͍ Ͱ͍͔ͬͨɹୈҰষ HippyVMͷέʔε

Slide 2

Slide 2 text

@mackee_w Ϛίϐʔ ๭ח૔ຊࣾԣ඿ࢧࣾ ຊ౰ʹPerlॻ͍͍ͯ·͢ ࠓ͸ιʔγϟϧήʔϜ৽ن։ൃαʔόαΠυ झຯ͸εϊʔϘʔυͱ౴͑Δͱձ࿩͕ࢭ·Δ

Slide 3

Slide 3 text

hippyVMͱ͸

Slide 4

Slide 4 text

hippyvm ΊͬͪΌ͸΍͍PHP HippyVM on average is 7.3x faster than stock PHP and 2x faster than Facebook's HHVM. Please check our benchmarks. ཁ໿͢ΔͱΊͬͪΌ͸΍͍

Slide 5

Slide 5 text

ͲΜͳ΋Μ͔͸uzulla͞Μͷ هࣄ͕ৄ͍͠ http://uzulla.hateblo.jp/entry/2014/03/25/143336 PypyͷPHP࣮ߦ؀ڥHippyVMࢼͨ͠ - uzulla͕ϒϩά

Slide 6

Slide 6 text

ͯ͞ຊ୊Ͱ͢

Slide 7

Slide 7 text

PyPyͬͯͳΜͩΑ͑Ζ͍ͷ͔

Slide 8

Slide 8 text

PyPyͱ͸PythonͰॻ͔Εͨ PythonΠϯλϓϦλͰ͢

Slide 9

Slide 9 text

ԿΛݴ͍ͬͯΔͷ͔Θ͔ΒͶʔͱ͓΋͏͕ ͋Γͷ··Ͱ͢

Slide 10

Slide 10 text

PyPy on RPython Toolchain

Slide 11

Slide 11 text

ͭ·ΓHippyVM͸PythonͰॻ͔ ΕͨPHPͱࢥͬͯ΋Β͑Ε͹Α͍

Slide 12

Slide 12 text

ҰൠతͳΠϯλϓϦλ/ίϯύ Πϥͷॲཧॱ 1. ίʔυΛτʔΫϯ୯Ґʹ෼ղ͢Δ(Lexer) 2. τʔΫϯΛந৅ߏจ໦(AST)ʹม׵͢Δ (Parser) 3. ASTΛVM্Ͱ࣮ߦ͢Δ

Slide 13

Slide 13 text

HippyVMΛಡΉ

Slide 14

Slide 14 text

main.py͔ΒΑΊ͹Α͍ def main(filename, rest_of_args, cgi, gcdump, debugger_pipes=(-1, -1)): try: f = open(filename) data = f.read() f.close() except: print "Error opening %s" % filename return 2 # space = getspace() interp = Interpreter(space) IJQQZNBJOQZ

Slide 15

Slide 15 text

main.py͔ΒΑΊ͹Α͍ try: ini_data = open('hippy.ini').read() except (OSError, IOError): ini_data = None if ini_data is not None: try: load_ini(interp, ini_data) except: os.write(2, "error reading `hippy.ini`") interp.setup(cgi, argv=[filename] + rest_of_args) absname = os.path.abspath(filename) bc = interp.compile_bytecode(absname, data) IJQQZNBJOQZ

Slide 16

Slide 16 text

interp͕͍Ζ͍Ζ΍͍ͬͯΔ def setup(self, cgi=False, argv=None): if self._setup: return space = self.space get, post = None, None if cgi: from hippy.cgisupport import setup_cgi self.web_config = setup_cgi(self, argv) self.cgi = True self.error_level = space.int_w(self.config.get_ini_w( 'error_reporting')) self._setup = True self.setup_globals(space, argv) IJQQZJOUFSQSFUFSQZ

Slide 17

Slide 17 text

interp͕͍Ζ͍Ζ΍͍ͬͯΔ def compile_bytecode(self, filename, source): try: return compile_php(filename, source, self.space, self) except (ParseError, LexerError) as exc: msg = "%s in %s on line %s" % (exc.message, filename, exc.source_pos) self.log_error(constants.E_PARSE, msg) return None except CompilerError as exc: msg = "%s in %s on line %s" % (exc.msg, exc.filename, exc.lineno) self.log_error(constants.E_ERROR, msg) return None IJQQZJOUFSQSFUFSQZ

Slide 18

Slide 18 text

compile_php ! def compile_php(filename, source, space, interp=None): phplexerwrapper = PHPLexerWrapper(source, filename, interp) if DEBUG: lst = [] while True: tok = phplexerwrapper.next() if tok is None: break else: lst.append(tok) print [x.__dict__ for x in lst] phplexerwrapper = iter(lst + [None]) parser = SourceParser(space, None, filename=filename) tokens = parser.parser.parse(phplexerwrapper, state=parser) bc = compile_ast(filename, source, tokens, space) return bc IJQQZQIQDPNQJMFSQZ

Slide 19

Slide 19 text

parse͚ͩΕͲlexer΋΍ͬͯΔ def parse(self): l = LexerWrapper(self.lexer) return self.parser.parse(l, state=self) IJQQZTPVSDFQBSTFSQZ

Slide 20

Slide 20 text

parse͚ͩΕͲlexer΋΍ͬͯΔ class LexerWrapper(BaseLexer): def __init__(self, lexer): self.lexer = lexer ! def next(self): while True: tok = self.lexer.token() if tok is None or tok.name not in ('H_NEW_LINE', 'H_WHITESPACE', 'T_COMMENT', 'H_TABULATURE'): return tok IJQQZTPVSDFQBSTFSQZ

Slide 21

Slide 21 text

τʔΧφΠζʙ def token(self): # தུ if self.pos >= self.heredoc_finish and self.heredoc_finish != -1: start = self.pos end = self.pos + self.heredoc_lgt assert start >= 0 assert end >= 0 tok = Token('T_END_HEREDOC', self.buf[start:end], self.lineno) self.pos = self.heredoc_finish + self.heredoc_lgt self.heredoc_finish = -1 self.heredoc_lgt = 0 self.context_stack.pop() return tok IJQQZMFYFSQZ

Slide 22

Slide 22 text

τʔΧφΠζʙ for token_regex, token_type in rules: pos = self.pos assert pos >= 0 m = self.match(token_regex, tmp_buf, pos) if m: start, end = self._getstartend(m) value = self.buf[start:end] if token_type == 'H_NEW_LINE': self.lineno += 1 elif token_type == 'T_COMMENT': self.lineno += value.count('\n') elif token_type == 'T_CONSTANT_ENCAPSED_STRING': self.lineno += value.count("\n") # tokens changing the context tok = Token(token_type, value, self.lineno) tok = self.maybe_change_context(ctx, tok, token_type, end) self.last_token = token_type IJQQZMFYFSQZ

Slide 23

Slide 23 text

m = self.match(token_regex, tmp_buf, pos)

Slide 24

Slide 24 text

RULES += [ ("b?\<\<\<.*?\n", 'T_START_HEREDOC'), ("\x00", 'T_END_HEREDOC'), # generated artificially ("\x00", 'T_ENCAPSED_AND_WHITESPACE'), # generated artificially ("\x00", 'T_IGNORE_THIS_TOKEN'), # generated artificially ! (r'b?"([^"\\]|\\.)*"|' + r"b?'([^'\\]|\\.)*'", 'T_CONSTANT_ENCAPSED_STRING'), ! ("[a-zA-Z_][a-zA-Z_0-9]*", 'T_STRING'), ! ("\?\>", 'B_END_OF_CODE_BLOCK'), ("\x00", 'B_LITERAL_BLOCK'), ! ("\+\=", 'T_PLUS_EQUAL'), ("\-\=", 'T_MINUS_EQUAL'), ("\*\=", 'T_MUL_EQUAL'), ("\/\=", 'T_DIV_EQUAL'), ("\.\=", 'T_CONCAT_EQUAL'), ("\%\=", 'T_MOD_EQUAL'), ("\&\=", 'T_AND_EQUAL'), ("\|\=", 'T_OR_EQUAL'),

Slide 25

Slide 25 text

No content

Slide 26

Slide 26 text

͍͍ͩͨ͜Ε͕τʔΧφΠζ ΍ͬͯΔͬΆ͍

Slide 27

Slide 27 text

ύʔαʔ͸ྗਚ͖ͨ rply͍ͬͯ͏RPython༻ͷ PLY(Python Lex-Yacc)Ͱ͢

Slide 28

Slide 28 text

ͦΜͳΘ͚Ͱݴޠ࡞Δͷʹ RPython Toolchainศརͦ͏