Slide 1

Slide 1 text

PHPͱRustΛ૊Έ߹ΘͤͯԻ੠ ϑΝΠϧΛΤϯίʔυ͢Δ࿩ PHPerKaigi 2020 LT @yaminoma_tw

Slide 2

Slide 2 text

Shumpei Urabe (@yaminoma_tw) ޷͖ͳϑϨʔϜϫʔΫ͸ BEAR.Sunday PHPerݟश͍

Slide 3

Slide 3 text

PHP FFIͷ͓͸ͳ͠

Slide 4

Slide 4 text

FFIͱ͸ʁ • PHPҎ֎ͷݴޠͰ࣮૷͞ΕͨωΠςΟϒίʔυΛݺͼग़͢͜ͱ ͕Ͱ͖Δ࢓૊Έ • FFI͸ωΠςΟϒ࣮ߦͳͷͰɺύϑΥʔϚϯεͷ޲্͕ظ଴Ͱ͖ Δ

Slide 5

Slide 5 text

PHP FFIͷྺ࢙ • Ҏલ͔ΒPECLͰFFIͷΤΫεςϯγϣϯ͸͋ͬͨ • ͔͠͠ɺ10೥Ҏ্ߋ৽͞Ε͍ͯͳ͍ঢ়گͰ์ஔ͞Ε͍ͯͨ

Slide 6

Slide 6 text

PHP FFIͷྺ࢙ • ͦ͜ͰZendࣾͷDmitry Stogovࢯ͸ɺlibffiΛ࢖֦ͬͨுΛ։ൃͨ͠ • 2019೥1݄ʹࢍ੒24ɺ൓ର15ͱ͍͏ൺֱతᷮࠩͰPHP 7.4΁ͷ࠾༻ ͕ܾ·Γɺ͜ͷ֦ு͕ແࣄPHP 7.4ʹऔΓࠐ·Εͨ • ͦͷ݁ՌɺPECLͷFFIΤΫεςϯγϣϯʹൺ΂ΔͱɺΠϯλʔϑΣ ΠεͷΈهड़͢Δ͚ͩͰग़དྷΔΑ͏ʹͳͬͨ

Slide 7

Slide 7 text

ຊ୊

Slide 8

Slide 8 text

PHPͰԻ੠ϑΝΠϧΛΤϯίʔυͯ͠ΈΔ • Ի੠ϑΝΠϧͷΤϯίʔυͱ͍͑͹FFmpeg͕ఆ൪Ͱ͋Δ • FFmpegͷίϚϯυΛexecͰୟ͘ͷ͸؆୯Ͱ͸͋Δ͕ɺexecͰ ࣮ߦͨ͘͠ͳ͍ͱ͖΋͋Δ • PHP୯ମͰԻ੠ϑΝΠϧΛΤϯίʔυͰ͖Δͱ௒ศརʂ

Slide 9

Slide 9 text

ͱ͍͏͜ͱͰ࡞Γ·ͨ͠

Slide 10

Slide 10 text

php-mp3-encoder • https://github.com/yaminoma/php-mp3-encoder • RustͰMP3ͷΤϯίʔμʔͰ͋Δlibmp3lameΛ࢖ͬͯɺWAVϑΝ Πϧ͔ΒMP3ʹΤϯίʔυ͢Δαϯϓϧ • ͜ͷlibmp3lame΋bindgenΛ࢖ͬͯRust͔ΒFFIͰݺͼग़͍ͯ͠Δ

Slide 11

Slide 11 text

͘͠Έ

Slide 12

Slide 12 text

wavͷத਎Λ uint8_t* Ͱ౉͢ Τϯίʔυͨ͠ϑΝΠϧ໊Λ char* Ͱ౉͢

Slide 13

Slide 13 text

PHPͰFFIΛ༗ޮʹͯ͠ΈΔ git clone https://github.com/php/php-src.git cd php-src git checkout PHP-7.4 ./configure --with-ffi make

Slide 14

Slide 14 text

PHPͰFFIΛ༗ޮʹͯ͠ΈΔ • σϑΥϧτ͸ ffi.enable=preload ʹͳ͓ͬͯΓɺϓϦϩʔυΛ ߦͬͨؔ਺·ͨ͸CLIΠϯλʔϑΣΠεͰͷΈFFIػೳΛ࢖༻͢ Δ͜ͱ͕Մೳ • ffi.enable=trueʹ͢ΔͱɺશͯͷFFIͷػೳΛ࢖͏͜ͱ͕ग़དྷΔ

Slide 15

Slide 15 text

RustͰΤϯίʔυ͢Δ෦෼Λ࣮૷͢Δ #[no_mangle] pub extern "C" fn encode(data: *mut u8, length: u32) -> *const c_char { unsafe { let buf: &mut [u8] = core::slice::from_raw_parts_mut(data, length as usize); let mut ptr = io::Cursor::new(buf); let mut wav_reader = hound::WavReader::new(&mut ptr).unwrap(); let mut data = Vec::new(); for sample in wav_reader.samples() { match sample { Ok(smpl) => data.push(smpl), _ => panic!("failed"), } } let timestamp = Rational64::from_integer(0); let raw_frame = RawFrame { timestamp, data }; let mut encoder = Encoder::new(); let output_file_name = encoder.encode(raw_frame); return CString::new(output_file_name) .expect("failed") .into_raw(); } }

Slide 16

Slide 16 text

RustͰdylibΛϏϧυͯ͠PHPͰαʔϒ͢Δ $ cargo build --release $ php -d ffi.enable=1 -S localhost:8000 -t src

Slide 17

Slide 17 text

μΠφϛοΫϥΠϒϥϦΛಡΈࠐΉ $signature = "const char* encode(uint8_t *data, uint32_t length);"; return \FFI::cdef( $signature, __DIR__ . "/../target/ release/libmp3encoder.dylib");

Slide 18

Slide 18 text

freadͰϑΝΠϧΛಡΈऔΔ $file = $_FILES['audio_file']['tmp_name']; $handle = fopen($file, "rb"); $fsize = filesize($file); $value = fread($handle, $fsize);

Slide 19

Slide 19 text

FFIͷݺͼग़͠ͱ࣮ߦ $ffi = loadLibrary(); $length = \strlen($value); $buffer = FFI::new(FFI::arrayType($ffi->type('uint8_t'), [$length])); FFI::memcpy($buffer, $value, $length); $bufferPtr = FFI::cast($ffi->type('uint8_t*'), $buffer); $outputFileName = $ffi->encode($bufferPtr, $length);

Slide 20

Slide 20 text

݁Ռ • 5෼ͷۂ͕େମ8ඵ͘Β͍Ͱม׵͕ऴΘͬͨ • PHPͷFFIͷυΩϡϝϯτ͕৘ใྔগͳͯ݁͘ߏۤ͠Μͩ • FFI͕༗ޮʹͳ͍ͬͯΕ͹ͲͷαʔόͰ΋MP3͕ΤϯίʔυͰ͖ Δʂ

Slide 21

Slide 21 text

FFIͷকདྷ • ܭࢉྔͷଟ͍ϓϩάϥϜΛFFIͰݺͼग़͢ͱྑ͍͔΋͠Εͳ͍ • ·ͩ·࣮ͩݧతͳཁૉ͕ଟ͍ͷͰɺϓϩμΫγϣϯϨσΟʔͰ ͸ͳ͍ • ͜Ε͔Βଞͷݴޠͱ૊Έ߹ΘͤͯPHP͕΋ͬͱ੝Γ্͕͍ͬͯ ͖͍ͨʂ

Slide 22

Slide 22 text

͓͠·͍