Goã¯ã¢ã»ã³ãã©ãŒé¢æ°ã®åŒã³åºããé©åã«ãµããŒãããŠãããæšæºã©ã€ãã©ãªã®å€§éã®éåžžã«é«éãªæå·åã³ãŒãã¯ãå®éã«ã¯ã20å以äžã®é床ãæäŸããæé©åãããã¢ã»ã³ãã©ãŒã§ãã
ããããã¢ã»ã³ãã©ãŒã³ãŒãã®èšè¿°ã¯äŸç¶ãšããŠå°é£ã§ããããããåæããããšã¯ããã«é£ãããæå·åã¯ééããèš±ããŸãã ã ãããã®é¢æ°ãããé«ãã¬ãã«ã®èšèªã§æžãããšãã§ãããçŽ æŽããããšæããŸãããïŒ
ãã®æçš¿ã¯ãã¢ã»ã³ãã©ãŒã®åŒã³åºããšæ¯èŒã§ããã»ã©é«éã«å®è¡ããããšããŠãGoããRustã³ãŒããåŒã³åºãããã®ãããã«äžé©åãªå®éšã«ã€ããŠã§ãã Rustãã³ã³ãã€ã©ã®å
éšãç¥ãå¿
èŠã¯ãªãããªã³ã«ãšã¯äœããç解ããã ãã§ãã
ãªãéã³ãã®ã§ããïŒ
ç§ã¯ããã«èªããŸã-ç§ã¯Rustãç¥ããŸããããããŠãããã«ã€ããŠæžããšããèãã¯ç§ã«ããŸãé
åçã§ã¯ãããŸããã ããã§ããRustã¯éåžžã«ãã調æŽããæé©åãããèšèªã§ãããã¢ã»ã³ãã©ãŒãããèªã¿ãããããšãç¥ã£ãŠããŸãã ïŒæçµçã«ã¯ããã¹ãŠãã¢ã»ã³ãã©ãããèªã¿ããããªããŸãïŒïŒ
Goã§ã¯ãéåžžãããã©ã«ãå€ã¯ã¡ã€ã³ã¿ã¹ã¯ã«åãããã«éžæãããããã©ã«ãã§ã¯é«éã§ããããšãä¿èšŒãããŠããæ©èœã®ã¿ãå«ãŸããŸã-ããã¯ãå€ãã®ãã©ã¡ãŒã¿ãå¿
èŠãšãã絶ãéãªãæåããéäºã«åœ¹ç«ã¡ãŸãã ç§ã¯åœŒã倧奜ãã§ãã ãããããã®åŸãä»æ¥è¡ãããšã®ããã«ãç¡å¹åãããã»ãã¥ãªãã£ãã§ãã¯ã§ã¹ã¿ãã¯ã®ã¿ã®é¢æ°ãçæããããã«èŠæ±ããå Žåã«ãç¬ãããªãèšèªãå¿
èŠã«ãªããŸãã
ãããŠãã¢ã»ã³ãã©ãŒã®ããã«æ¯ãèãããã«ååã«å¶éããã¢ã»ã³ãã©ãŒãšåããããå¹ççã«ãªãããã«æé©åã§ãããããªèšèªãããå Žåãããã¯ããããRustã«ãªããŸãã
æçµçã«ãRustã¯å®å
šã§ãç©æ¥µçã«éçºãããŠãããéèŠãªããšãšããŠã䜿çšå¯èœãªé«éæå·åã³ãŒãã®åªãããšã³ã·ã¹ãã ãæ¢ã«æã£ãŠããŸãã
ãªãcgoã§ã¯ãããŸãããïŒ
Goã«ã¯ã Foreign Function Interfaceããã ããã®ãŸãŸäœ¿çšã§ããŸãã cgoã䜿çšãããšãGoããã°ã©ã ã¯æãèªç¶ãªæ¹æ³ã§Cé¢æ°ãåŒã³åºãããšãã§ããŸããæ®å¿µãªãããããã¯ãŸã£ããèªç¶ãªããšã§ã¯ãããŸããã ïŒç§ã¯cgoã«ã€ããŠç§ãæãã§ãããããå€ãã®ããšãç¥ã£ãŠããŸãããããŠãç§ãä¿¡ããŠãããã¯å
šãé¢çœããªãã§ãïŒã
C ABIãFFIã®ãlingua francaããšããŠäœ¿çšãããšãã©ãããã§ãåŒã³åºãããšãã§ããŸããRustã¯C ABIãšäºææ§ã®ããã©ã€ãã©ãªã«ã³ã³ãã€ã«ã§ããcgoã¯ããã䜿çšã§ããŸãã ããã¯æãã§ãããåäœããŸãã
éã«ãGoãCã©ã€ãã©ãªã«ã³ã³ãã€ã«ããŠãããŸããŸãªèšèªããåŒã³åºãããšãã§ããŸããããšãã°ãç§ã¯Pythonãããªãã¯ãšããŠå®è¡ããŸãã ã ïŒäººã
ãããã¯åãªãããªãã¯ã§ãããçå£ã«åãåããªãã§ãã ããïŒ
ããããcgoã¯Goã®èªç¶ããå°ãè¿œå ããããã«å
éšã§å€ãã®ããšãè¡ããŸã.Cã³ãŒãã®ã¹ã¿ãã¯ãç·šæããGoåŒã³åºãã§ãããã¯ãçºçããå Žåã«æ£ããåäœããããã«å»¶æåŒã³åºããã»ããã¢ããããŸã...ããã«ã€ããŠã¯å¥ã®æçš¿ãæžãããšãã§ããŸãã
ãããããã®çµæãåcgoåŒã³åºãã®ã³ã¹ãã¯ãä»æ¥ã話ãããŠãããããªã軜快ãªå°ããªé¢æ°ã®å Žåã«ã¯é«ãããŸã ã
ãã¹ãŠãäžç·ã«ç·šã
äžè¬ã«ããã®èãïŒã¢ã»ã³ãã©ãŒãRustã®ã³ãŒããªã©ã®åé¢ã³ãŒããããå Žåãçè«çã«ã¯ãã¢ã»ã³ãã©ãŒãšåæ§ã«ããã䜿çšããŠçŽæ¥åŒã³åºãããšãã§ããã¯ãã§ãã èãå±€ã§ãããŸããŸããã
äžçšåºŠã®IRã¬ãã«ã§äœæ¥ããããšã¯æãŸãããããŸãããGoã³ã³ãã€ã©ãŒã¯ã Go 1.3ããå§ããŠãåã¶åã«ãGoã³ãŒããšã¢ã»ã³ãã©ãŒã®äž¡æ¹ããã·ã³ã³ãŒãã«å€æããŸãã
ããã¯ãã·ã¹ãã ãªã³ã«ãŒã䜿çšããŠGoã§ããã°ã©ã ããªã³ã¯ãããšãã«ãå€éšãªã³ã¯ããªã©ã®æŠå¿µãååšããããšã§ç¢ºèªãããŸãã ããã¯ãcgoã®åäœãšãŸã£ããåãã§ããæåã«ãCã¯Cã³ã³ãã€ã©ãGo-Goã³ã³ãã€ã©ã§ã³ã³ãã€ã«ããããããã¯ãã¹ãŠclang
ãŸãã¯gcc
ã䜿çšããŠãªã³ã¯ãããŸãã CGO_LDFLAGS
ãä»ããŠãæŠèŠã«ãã©ã°ãçŽæ¥æž¡ãããšãã§ããŸãã
cgoã®ãã¹ãŠã®ã»ãã¥ãªãã£å¯Ÿçã®è£ã§ã¯ããã¡ãããæçµçã«ã¯å€èšèªã®èª²é¡èªäœãèŠã€ãããŸãã
ãããããã¡ãããã³ã³ãã€ã©ãå€æŽããã«ãããè¡ãæ¹æ³ãèŠã€ããããšã¯çŽ æŽãããããšã§ãã ãŸããGoããã°ã©ã ãRustã¢ãŒã«ã€ãã«ãªã³ã¯ããæ¹æ³ãèŠãŠã¿ãŸãããã
#cgo
ãã£ã¬ã¯ãã£ãã䜿çšããå Žåãé€ãã go build
ã䜿çšããŠå€éšãã€ããªã«ãªã³ã¯ããéåžžã®æ¹æ³ãèŠã€ããããšãã§ããŸããã§ããïŒãã®çç±ã¯ïŒïŒã ãã ããcgoåŒã³åºãã¯.sãã¡ã€ã«ãäœæããŸãããã®ãã¡ã€ã«ã¯ãGoã§ã¯ãªãCã³ã³ãã€ã©ã«æž¡ãããŸããã€ãŸããGoã¢ã»ã³ãã©ãå¿
èŠã§ããããšãæå³ããŸãã
幞ããªããšã«ã go / buildã¯åãªãããã³ããšã³ãã§ãïŒ Goã¯ãããã°ã©ã ã®ã³ã³ãã€ã«ãšãªã³ã¯ã®ããã®äžé£ã®äœã¬ãã«ãŠãŒãã£ãªãã£ãæäŸããŸããgobuildã¯ããã¡ã€ã«ãåéããŠæã«ãããããã®ãŠãŒãã£ãªãã£ãå®è¡go build
ã ãã§ãã -x
ãã©ã°ã§äœãèµ·ãããã远跡ã§ããŸãã
-x -ldflags "-v -linkmode=external '-extldflags=-v'"
ãããšãã«-x -ldflags "-v -linkmode=external '-extldflags=-v'"
åŒã³åºãã«äŒŒãå°ããªMakefileãäœæããŸããã
rustgo: rustgo.a go tool link -o rustgo -extld clang -buildmode exe -buildid b01dca11ab1e -linkmode external -v rustgo.a rustgo.a: hello.go hello.o go tool compile -o rustgo.a -p main -buildid b01dca11ab1e -pack hello.go go tool pack r rustgo.a hello.o hello.o: hello.s go tool asm -I "$(shell go env GOROOT)/pkg/include" -D GOOS_darwin -D GOARCH_amd64 -o hello.o hello.s
ããã«ããã1ã€ã®Goãã¡ã€ã«ïŒ hello.go
ïŒãšã¢ã»ã³ãã©ãŒGoãã¡ã€ã«ïŒ hello.s
ïŒã§æ§æãããåçŽãªã¡ã€ã³ããã±ãŒãžãäœæãããŸãã
ããŠããªããžã§ã¯ããRustã«ãªã³ã¯ãããå ŽåããŸãéçã©ã€ãã©ãªãšããŠãã«ãããå¿
èŠããããŸã...
libhello.a: hello.rs rustc -g -O --crate-type staticlib hello.rs
...ãããŠãå€éšãªã³ã«ã«ãããããªã³ã¯ããããã«æ瀺ããŸãã
rustgo: rustgo.a libhello.a go tool link -o rustgo -extld clang -buildmode exe -buildid b01dca11ab1e -linkmode external -v -extldflags='-lhello -L"$(CURDIR)"' rustgo.a
$ make go tool asm -I "/usr/local/Cellar/go/1.8.1_1/libexec/pkg/include" -D GOOS_darwin -D GOARCH_amd64 -o hello.o hello.s go tool compile -o rustgo.a -p main -buildid b01dca11ab1e -pack hello.go go tool pack r rustgo.a hello.o rustc --crate-type staticlib hello.rs note: link against the following native artifacts when linking against this static library note: the order and any duplication can be significant on some platforms, and so may need to be preserved note: library: System note: library: c note: library: m go tool link -o rustgo -extld clang -buildmode exe -buildid b01dca11ab1e -linkmode external -v -extldflags="-lhello -L/Users/filippo/code/misc/rustgo" rustgo.a HEADER = -H1 -T0x1001000 -D0x0 -R0x1000 searching for runtime.a in /usr/local/Cellar/go/1.8.1_1/libexec/pkg/darwin_amd64/runtime.a searching for runtime/cgo.a in /usr/local/Cellar/go/1.8.1_1/libexec/pkg/darwin_amd64/runtime/cgo.a 0.00 deadcode 0.00 pclntab=166785 bytes, funcdata total 17079 bytes 0.01 dodata 0.01 symsize = 0 0.01 symsize = 0 0.01 reloc 0.01 dwarf 0.02 symsize = 0 0.02 reloc 0.02 asmb 0.02 codeblk 0.03 datblk 0.03 sym 0.03 headr 0.06 host link: "clang" "-m64" "-gdwarf-2" "-Wl,-headerpad,1144" "-Wl,-no_pie" "-Wl,-pagezero_size,4000000" "-o" "rustgo" "-Qunused-arguments" "/var/folders/ry/v14gg02d0y9cb2w9809hf6ch0000gn/T/go-link-412633279/go.o" "/var/folders/ry/v14gg02d0y9cb2w9809hf6ch0000gn/T/go-link-412633279/000000.o" "-g" "-O2" "-lpthread" "-lhello" "-L/Users/filippo/code/misc/rustgo" 0.34 cpu time 12641 symbols 5764 liveness data
Rustãž
ãªã³ã¯ããŸããããã·ã³ãã«èªäœã¯ãåã«ãã€ããªãã¡ã€ã«ã§é£ãåã£ãŠåº§ã£ãŠããã ãã§ã¯äœãã§ããŸããã Goã³ãŒãããRusté¢æ°ãäœããã®æ¹æ³ã§åŒã³åºãå¿
èŠããããŸãã
GoããGoé¢æ°ãåŒã³åºãæ¹æ³ã¯æ¢ã«ç¥ã£ãŠããŸãã ã¢ã»ã³ãã©ãŒã§ã¯ããã®åŒã³åºãã¯CALL hello(SB)
ããã«ãªããŸããããã§ãSBã¯ãã¹ãŠã®ã°ããŒãã«æåã§ã¢ã¯ã»ã¹å¯èœãªä»®æ³ã¬ãžã¹ã¿ã§ãã
Goããã¢ã»ã³ãã©ãŒã§é¢æ°ãåŒã³åºãå Žåãã³ã³ãã€ã©ãŒã«ãã®ããšãç¥ãããå¿
èŠããããŸã-CããããŒã®ãããªãã®ã§ãé¢æ°ã®æ¬äœãªãã§func hello()
ã®ã¿ãèšè¿°ããŸãã
å€éšRusté¢æ°ã®åŒã³åºãã®äžèšã®çµã¿åããããã¹ãŠè©ŠããŸããããé¢æ°ã®ã·ã³ãã«ãŸãã¯æ¬äœã衚瀺ãããªããšããäžæºããããŸããã
ããããæçµçã«ã¯åãªã倧ããªã³ãŒããžã§ãã¬ãŒã¿ãŒã§ããcgoã¯ãã©ãããããããã®ãšã€ãªã¢ã³é¢æ°ãåŒã³åºãããšãã§ããŸãïŒ ããããã©ã®ããã«ïŒ
ç§ã¯æ°æ¥åŸã«çãã«åºäŒããŸãã ã
é¢çœããã©ã°ãã®ããã«èŠããŸãïŒ //go:linkname
ã¯ãããŒã«ã«ã¹ã³ãŒãïŒ ãã©ã€ããŒãé¢æ°ãåŒã³åºãããã«äœ¿çšã§ããïŒ ïŒå
ã®æåã®ãšã€ãªã¢ã¹ãäœæããã ãã§ããããã§ã®byte
ããªãã¯ã¯ãããçš®ã®ã¢ãã¬ã¹æäœã®ããã ãã§ãããšç¢ºä¿¡ããŠãbyte
//go:cgo_import_static
...å€åãã€ã³ããŒãããŸãïŒ
ãã®æ°ããç¥èãšäžèšã®Makefileã䜿çšããŠãRustïŒhello.rsïŒããé¢æ°ãåŒã³åºãããšãã§ããŸãã
#[no_mangle] pub extern fn hello() { println!("Hello, Rust!"); }
ïŒãã³ã°ã«/ãã/ãšã¯ã¹ã¿ãŒã³ã®ãªãéè¡ã¯ã ãã®ãã¥ãŒããªã¢ã«ããåãããŠããŸã ïŒ
ãããŠãGoïŒ hello.go
ïŒã§ãã®ããã°ã©ã ããåŒã³åºããŸãïŒ
package main
ãã®ã¢ã»ã³ãã©ãŒã®äŸã䜿çšïŒ hello.s
ïŒïŒ
TEXT ·trampoline(SB), 0, $2048 JMP hello(SB) RET
CALL
ã¯æŽç·ŽãããããŠäœ¿çšã§ããŸããã§ããããåçŽãªJMP
ã䜿çšããŠ...
Hello, Go! Hello, Rust! panic: runtime error: invalid memory address or nil pointer dereference [signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x0]
ããŠãçµäºããããšãããšãã«ããã°ã©ã ãã¯ã©ãã·ã¥ããŸããã ãããŠä»ããã®$2048
å€ã¯Rustãäžããã¹ã¿ãã¯å
šäœã§ããïŒã¹ã¿ãã¯ãããã¹ãå Žæã«çœ®ãå ŽåïŒãRustãå°ãªããšãããŒãã«è§Šããããšããå Žåã«äœãèµ·ãããã¯å°ããŸãã...ããããããŸããŸãããç§ã¯ããããŸã£ããæ©èœããããšã«é©ããŠããŸãïŒ
åŒã³åºãèŠçŽ
ããã°ã©ã ããããã«çµäºããããçš®ã®åŒæ°ãæž¡ãããå Žåã¯ãGo and Rustã®åŒã³åºãèŠçŽãããã«è©³ãã調ã¹ãå¿
èŠããããŸãã ãããã®èŠåã«ãããé¢æ°åŒã³åºãéã§åŒæ°ãšæ»ãå€ãé
眮ãããå Žæã決ãŸããŸãã
Goã®åŒã³åºãèŠåã«ã€ããŠã¯ã ãããšããã§èª¬æããŸã ã Rustã®å Žåã FFIã®æšæºã調ã¹ãå¿
èŠããããŸãããããã¯Cã®æšæºçãªåæã«ãããŸããã
ç¶è¡ããã«ã¯ããããã¬ãå¿
èŠã§ãã ïŒLLDBã¯GoããµããŒãããŠããŸãããMacOS Xã§ã¯ãã¬ãŒã¯ãã€ã³ãã倱æãããããç¹æš©Dockerã³ã³ãããŒå
ã§ãããè¡ãå¿
èŠããããŸããïŒ

é話å¥çŽ

Goã®åŒã³åºãèŠçŽã¯ã»ãšãã©ææžåãããŠããŸããããããã«é²ãã«ã¯ãããç解ããå¿
èŠãããããããã®éã¢ã»ã³ãã©ãŒãªã¹ãïŒamd64ïŒããåŠã¶ããšãã§ããŸãã éåžžã«åçŽãªé¢æ°ãèŠãŠã¿ãŸãããïŒ
// func foo(x, y uint64) uint64 TEXT ·foo(SB), 0, $256-24 MOVQ x+0(FP), DX MOVQ DX, ret+16(FP) RET
foo
ã¯256ïŒ0x100ïŒãã€ãã®ããŒã«ã«ãã¬ãŒã ã16ãã€ãã®åŒæ°ã8ãã€ãã®æ»ãå€ããããæåã®åŒæ°ã®ã¿ãè¿ããŸãã
func main() { foo(0xf0f0f0f0f0f0f0f0, 0x5555555555555555)
rustgo[0x49d785]: movabsq $-0xf0f0f0f0f0f0f10, %rax rustgo[0x49d78f]: movq %rax, (%rsp) rustgo[0x49d793]: movabsq $0x5555555555555555, %rax rustgo[0x49d79d]: movq %rax, 0x8(%rsp) rustgo[0x49d7a2]: callq 0x49d8a0 ; main.foo at hello.s:14
äžèšã®åŒã³åºãã³ãŒãã¯ã»ãšãã©äœãããŸããïŒãã¬ãŒã ã®äžéšã«ããéã®é åºã§ã¹ã¿ãã¯ã«åŒæ°ã眮ãïŒ rsp
ãã16(rsp)
ã«ãã¹ã¿ãã¯ã倧ãããªãããšãå¿ããªãã§ãã ããïŒã CALL
ãåŒã³åºããŸãã CALL
åŒã³åºããšãæ»ãå€ãžã®ãã€ã³ã¿ãŒãã¹ã¿ãã¯ã«ããã·ã¥ããããžã£ã³ãããŸãã ããã«ã¯åŒã³åºãé¢æ°ã®ã¯ãªã¢ã¯ãªããæåŸã«åçŽãªRET
ããããŸãã
rsp
ä¿®æ£ãããŠããããšã«æ³šæããŠãã ãããããã§ã¯movq
代ããã«movq
ããããŸã
rustgo`main.foo at hello.s:14: rustgo[0x49d8a0]: movq %fs:-0x8, %rcx rustgo[0x49d8a9]: leaq -0x88(%rsp), %rax rustgo[0x49d8b1]: cmpq 0x10(%rcx), %rax rustgo[0x49d8b5]: jbe 0x49d8ee ; main.foo + 78 at hello.s:14 [...] rustgo[0x49d8ee]: callq 0x495d10 ; runtime.morestack_noctxt at asm_amd64.s:405 rustgo[0x49d8f3]: jmp 0x49d8a0 ; main.foo at hello.s:14
æåã®4ã€ã®é¢æ°åœä»€ãšæåŸã®2ã€ã®é¢æ°åœä»€ã¯ãã¹ã¿ãã¯ã«ååãªã¹ããŒã¹ããããã©ããããã§ãã¯ããã¹ããŒã¹ããªãå Žåã¯ã runtime.morestack
ãåŒã³åºãruntime.morestack
ã NOSPLIT
ãšã©ãã«ä»ããããé¢æ°ã§ã¯ããããã¯ããããã¹ããããããŸãïŒ
rustgo[0x49d8b7]: subq $0x108, %rsp [...] rustgo[0x49d8e6]: addq $0x108, %rsp rustgo[0x49d8ed]: retq
次ã«ã rsp
ã³ã³ãããŒã«ã䜿çšããŸãããã®ã³ã³ãããŒã«ã§ã¯ã0x108ãæžç®ãããäžåºŠã«ãã¬ãŒã çšã®0x100ãã€ããšãã€ã³ã¿ãŒçšã®8ãã€ãã®ã¹ããŒã¹ã解æŸãããŸãã ãã®çµæã rsp
ã¯é¢æ°ãã¬ãŒã ã®äžéšïŒçµäºïŒãæããåŒã³åºãããé¢æ°ã«ãã£ãŠå¶åŸ¡ãããŸãã æ»ãåã«ã rsp
ã¯å
ã®å ŽæïŒãªã¿ãŒã³ãã€ã³ã¿ã®çŽåŸïŒã«æ»ããŸãã
rustgo[0x49d8be]: movq %rbp, 0x100(%rsp) rustgo[0x49d8c6]: leaq 0x100(%rsp), %rbp [...] rustgo[0x49d8de]: movq 0x100(%rsp), %rbp
æåŸã«ããã¬ãŒã ãžã®ãã€ã³ã¿ãŒã¯ãæ¬è³ªçã«ããªã¿ãŒã³ãã€ã³ã¿ãŒã®çŽåŸã«ã¹ã¿ãã¯ã«rbp
ãã rbp
ã§æŽæ°ããrbp
ã rbp
ãåŒã³åºãããé¢æ°ã«ãã£ãŠä¿åãããã¹ã¿ãã¯ãã¹ãã³ã§ããããã«ããããã«ãåŒã³åºãããé¢æ°ãrbp
ãä¿åããå Žæã§æŽæ°ããå¿
èŠãããããšãrbp
ãŸããã
rustgo[0x49d8ce]: movq 0x110(%rsp), %rdx rustgo[0x49d8d6]: movq %rdx, 0x120(%rsp)
ãã®çµæãé¢æ°æ¬äœãããæ»ãå€ãåŒæ°ã®ããäžã«ããããšãããããŸããã
ä»®æ³ã¬ãžã¹ã¿
Goã®ããã¥ã¡ã³ãã§ã¯ã SP
ãšFP
ã¯rsp
ãšrbp
ãšã€ãªã¢ã¹ã§ã¯ãªããä»®æ³ã¬ãžã¹ã¿ã§ãããšrbp
ãŸãã
Goã¢ã»ã³ãã©ããSP
ã䜿çšãããšã SP
ããã¬ãŒã ã®äžéšã§ã¯ãªãäžéšãæãããã«ããã¹ãŠã®ãªãã»ãããå®éã®ã¬ãžã¹ã¿rsp
ã«å¯ŸããŠåèšç®ãããããšã¯æããã§ãã ããã¯ããã¬ãŒã ã®ãµã€ãºãå€æŽããããšãã«ãã¹ãŠã®ãªãã»ãããå€æŽã§ããªãå¯èœæ§ãããããšãæå³ããããã䟿å©ã§ãããããã¯å®éã«ã¯åãªãæ§æäžã®ã·ã¥ã¬ãŒã§ãã ãã¢ã¬ãžã¹ããªã¢ã¯ã»ã¹ïŒ MOV SP, DX
ïŒã¯ã rsp
çŽæ¥ã¢ã¯ã»ã¹ããŸãã
ä»®æ³FP
ã¬ãžã¹ã¿ãrsp
é¢é£ããŠårsp
ãŸãã ããã¯ãåŒã³åºãåŽã®é¢æ°ã®ãã¬ãŒã ã®äžçªäžãæããåŒæ°ããããçŽæ¥ã¢ã¯ã»ã¹ã§ããŸããã
泚ïŒGoã¯rbp
ããã³ãã¬ãŒã ãã€ã³ã¿ãŒãä¿åããŠãããã°ãæ¯æŽããŸãããä»®æ³FP
rsp
ããã³rsp
åºå®omit-stack-pointer
ã¹ã¿ã€ã«omit-stack-pointer
ãåºå®ããŠäœ¿çšãomit-stack-pointer
ã ãã¬ãŒã ãžã®ãã€ã³ã¿ãŒãšãã¢ãã ã©ã³ã°ã¬ãŒã«ãããã®æçš¿ã§ã®äœ¿çšæ¹æ³ã«ã€ããŠè©³ããèªãããšãã§ããŸãã
Cã®åŒã³åºãèŠçŽ
Cã§ã¯ãæšæºã®x86-64åŒã³åºãèŠçŽã¯sysv64
ã§ããããŸã£ããç°ãªããŸãã
- åŒæ°ã¯ã¬ãžã¹ã¿ãä»ããŠæž¡ãããŸãïŒRDIãRSIãRDXãRCXãR8ãR9
- æ»ãå€ã¯RAXã«éãããŸã
- äžéšã®ã¬ãžã¹ã¿ã¯ãåŒã³åºãããé¢æ°RBPãRBXãããã³R12-R15ã«ãã£ãŠä¿åãããŸã
- Goã§ã¯ãåŒã³åºãããé¢æ°ã«ãã£ãŠãã¹ãŠã®ã¬ãžã¹ã¿ãä¿åããããããããã¯ã»ãšãã©é¢å¿ããããŸããã
- ã¹ã¿ãã¯ã¯16ãã€ãã§æŽåããã
- ïŒã ãããã
JMP
ã¯æ©èœãããã CALL
ã¯æ©èœããªãã£ã-ã¹ã¿ãã¯ã調æŽããªãã£ãïŒïŒ
rustc
ãåãããã«æ©èœããŸãïŒ -g
ãšãšãã«rustc
ã䜿çšããŠçæãããŸãïŒã
ãã¹ãŠããŸãšãã
2ã€ã®å¥çŽã®éã«åçŽãªèžã¿å°ãäœæããããšã¯é£ãããããŸããã ã€ã³ã¹ãã¬ãŒã·ã§ã³ã«ã€ããŠã¯asmcgocall
ãèŠãããšãã§ããŸããããã¯asmcgocall
ã«ã€ããŠã®ã¿ã§ãã
Goãã¢ã»ã³ãã©é¢æ°ã®ã¹ã¿ãã¯ã䜿çšããããã«ãããã®ã¯èŠããŠããå¿
èŠããããŸããGoãååšããããšãä¿èšŒããŠããããã§ãã ãããè¡ãã«ã¯ãã¹ã¿ãã¯ã®æåŸã«rsp
ãè¿ãå¿
èŠããããŸãã
package main
TEXT ·trampoline(SB), 0, $2048-16 MOVQ arg+0(FP), DI // Load the argument before messing with SP MOVQ SP, BX // Save SP in a callee-saved registry ADDQ $2048, SP // Rollback SP to reuse this function's frame ANDQ $~15, SP // Align the stack to 16-bytes CALL increment(SB) MOVQ BX, SP // Restore SP MOVQ AX, ret+8(FP) // Place the return value on the stack RET
#[no_mangle] pub extern fn increment(a: u64) -> u64 { return a + 1; }
macOSã§ã®åŒã³åºã
å®éã CALL
ã¯macOSãšããŸã仲ãè¯ããããŸããã äœããã®çç±ã§ãé¢æ°åŒã³åºããcgo_thread_start
äžéåŒã³åºãã«çœ®ãæããããŸãããããã¯ã cgo_import_static
ãšåŒã°ãããã®ã䜿çšããGoã¢ã»ã³ãã©ãŒã§ãCALL
cgo_import_static
ããããšãèãããšãããã»ã©å¥åŠã§ã¯ãããŸããã
callq 0x40a27cd ; x_cgo_thread_start + 29
//go:linkname
ã䜿çšããŠãã®ããã«ãããåé¿ã§ããŸããããã¯ãæšæºã©ã€ãã©ãªã§é¢æ°ãžã®ãã€ã³ã¿ãååŸãã次ã®ããã«é¢æ°ãã€ã³ã¿ãåŒã³åºããŸãã
import _ "unsafe"
MOVQ ·_increment(SB), AX CALL AX
éãã§ããïŒ
ãã®å®éšã®å
šã¿ã¹ã¯ã¯ãæå·æäœã®ããã«ã¢ã»ã³ãã©ãŒã®ä»£ããã«RustãåŒã³åºãããšã§ããïŒæ¥œããã§ãã ããïŒã ãããã£ãŠãrustgoåŒã³åºãã¯ãã¢ã»ã³ãã©ãŒåŒã³åºããšåããããé«éã§ããå¿
èŠããããŸãã
ãã³ãããŒã¯æéïŒ
ã€ã³ã©ã€ã³ããŒãžã§ã³ã§ã®uint64å€æ°ã®å¢å ãã //go:noinline
ãã£ã¬ã¯ãã£ããrustgoåŒã³åºããããã³Rusté¢æ°èªäœã®cgoåŒã³åºããšæ¯èŒããŸãã
Rustã¯-g -O
ãã©ã°ã䜿çšããŠã³ã³ãã€ã«ããããã³ãããŒã¯ã¯2.9GHz Intel Code i5ããã»ããµãŒäžã®macOSã§å®è¡ãããŸããã
name time/op CallOverhead/Inline 1.72ns ± 3% CallOverhead/Go 4.60ns ± 2% CallOverhead/rustgo 5.11ns ± 4% CallOverhead/cgo 73.6ns ± 0%
rustgoã¯ãéåžžã®Goé¢æ°ãåŒã³åºãããã11ïŒ
é
ããcgoãããã»ãŒ15åé«éã§ãïŒ
Linuxã§ã¯ãã€ã³ã¿ãŒã®åé¡ããªããçµæã¯ããã«è¯ããªãã2ïŒ
ã ãé
ããªããŸãã
name time/op CallOverhead/Inline 1.67ns ± 2% CallOverhead/Go 4.49ns ± 3% CallOverhead/rustgo 4.58ns ± 3% CallOverhead/cgo 69.4ns ± 0%
å®éã®äŸ
å®éã®äŸãšããŠããã°ãããã©ã€ãã©ãªcurve25519-dalekãéžæããŸãããå
·äœçã«ã¯ãæ²ç·ã®éå§ç¹ã«ã¹ã«ã©ãŒãæããŠããã®Edwardsè¡šçŸãè¿ãã¿ã¹ã¯ãéžæããŸããã
貚ç©ã®ãã³ãããŒã¯ã¯ãããã»ããµã®åšæ³¢æ°ãåçã«å€åãããããæã¡äžãéã§å€§ããç°ãªããŸãããæäœã22.9µs±17ïŒ
ãå ãããšããããçŽæããŸãã
test curve::bench::basepoint_mult ... bench: 17,276 ns/iter (+/- 3,057) test curve::bench::edwards_compress ... bench: 5,633 ns/iter (+/- 858)
GoåŽã§ã¯ãåçŽãªAPIãè¿œå ããŸãã
func ScalarBaseMult(dst, in *[32]byte)
RuståŽã§ã¯ãããã¯éåžžã®FFIã®ã€ã³ã¿ãŒãã§ã€ã¹ãæ§ç¯ããããšãšå€§å·®ãããŸããã
ççŽã«èšã£ãŠãRustã§ãããæ©èœãããã«ã¯æ°žé ã«æéãããããŸããã
#![no_std] extern crate curve25519_dalek; use curve25519_dalek::scalar::Scalar; use curve25519_dalek::constants; #[no_mangle] pub extern fn scalar_base_mult(dst: &mut [u8; 32], k: &[u8; 32]) { let res = &constants::ED25519_BASEPOINT_TABLE * &Scalar(*k); dst.clone_from(res.compress_edwards().as_bytes()); }
.a
ãäœæããã«ã¯ã Cargo.toml
cargo build --release
ãCargo.toml
ã§å®è¡ãCargo.toml
ããã¯ãäŸåé¢ä¿ã瀺ãããã¬ãŒã ãžã®ãã€ã³ã¿ãŒãå«ã¿ãæšæºã©ã€ãã©ãªãªãã§æãé«åºŠãªæ°åŠã䜿çšããããã«curve25519-dalekãæ§æããŸãã
[package] name = "ed25519-dalek-rustgo" version = "0.0.0" [lib] crate-type = ["staticlib"] [dependencies.curve25519-dalek] version = "^0.9" default-features = false features = ["nightly"] [profile.release] debug = true
ããã§ããã¹ããªã³ã°ããŒããä¿®æ£ããŠã2ã€ã®åŒæ°ãåããäœãè¿ããªãããã«ããå¿
èŠããããŸãã
TEXT ·ScalarBaseMult(SB), 0, $16384-16 MOVQ dst+0(FP), DI MOVQ in+8(FP), SI MOVQ SP, BX ADDQ $16384, SP ANDQ $~15, SP MOVQ ·_scalar_base_mult(SB), AX CALL AX MOVQ BX, SP RET
ãã®çµæãGoããã®ééçãªåŒã³åºããè¡ãããçŽç²ãªGoã®ãã³ãããŒã¯ã«å¹æµããé床ã§ãcgoãããã»ãŒ6ïŒ
é«éã«ãªããŸãã
name old time/op new time/op delta RustScalarBaseMult 23.7µs ± 1% 22.3µs ± 4% -5.88% (p=0.003 n=5+7)
æ¯èŒã®ããã«ãGoããã±ãŒãžgithub.com/agl/ed25519/edwards25519
åæ§ã®æ©èœ-çŽç²ãªGoå®è£
ã§ã¯ãã»ãŒ3åã®æéãããããŸãã
h := &edwards25519.ExtendedGroupElement{} edwards25519.GeScalarMultBase(h, &k) h.ToBytes(&dst)
name time/op GoScalarBaseMult 66.1µs ± 2%
ãã¹ãŠãŸãšããŠæ¢±å
ãã
ããã§æ¬åœã«ããŸãããããšãããããŸããïŒ ãããããããå®éã«äœ¿çšã§ããããã«ããã«ã¯ããœãªã¥ãŒã·ã§ã³ã¯ãæ³¥ã ããã®ãã«ãããã»ã¹ã䜿çšããŠpackage main
匷å¶çã«æ¿å
¥ããã®ã§ã¯ãªããã€ã³ããŒãã§ããããã±ãŒãžã®åœ¢åŒã«ããå¿
èŠããããŸãã
ãããŠãã//go:binary-only-package
ãç»å ŽããŸãã ãã®æ³šéã«ããããœãŒã¹ã³ãŒããç¡èŠãã以åã«åéãã$GOPATH/pkg
.a
ã©ã€ãã©ãªãã¡ã€ã«ã®ã¿ã䜿çšããããšãã§ããŸãã
ãã€ãã£ãã®Goãªã³ã«ãŒïŒ cmd / link ã å
éšãªã³ã«ãŒãšãåŒã°ããŸãïŒã§åäœãã.a
ãã¡ã€ã«ãæ§ç¯ã§ããã°ã ãããé
åžã§ããŸããããã«ããããŠãŒã¶ãŒã¯ã¯ãã¹ã³ã³ãã€ã«ãå«ããã€ãã£ãã³ãŒãã§ãããã®ããã«ããã±ãŒãžãã€ã³ããŒãã§ããŸã ïŒæé»çã«ãã®ãã©ãããã©ãŒã çšã«.a
ãäœæããŸãïŒïŒ
å€ãã®å ŽåãGoã¯ã·ã³ãã«ã§ãæ¢ã«ã¢ã»ã³ãã©ãŒãšRustã®ãã¢ããããŸãã go doc
ã§è¡šç€ºã§ããããã«ããã¥ã¡ã³ããè¿œå ããããšãã§ããŸãã
makefileã¯ãããã«å€æŽãããŸããããã¯ãã©ã€ãã©ãªãæ§ç¯ããªããªã£ãããgo tool link
䜿çšãåæ¢ã§ãgo tool link
ã
.a
ã¢ãŒã«ã€ã.a
ã¯ãæåããŒãã«ãšãšãã«å€ä»£åœ¢åŒã®ãªããžã§ã¯ã.o
ãã¡ã€ã«ã®ã³ã¬ã¯ã·ã§ã³ã§ãã ã·ã³ãã«ãlibed25519_dalek_rustgo.a
ããlibed25519_dalek_rustgo.a
ã¢ãŒã«ã€ãã«libed25519_dalek_rustgo.a
ã go tool compile
libed25519_dalek_rustgo.a
ã§ããããã«ããã°ãç®æšãéæã§ããŸãã
.a
ã¢ãŒã«ã€ãã¯ãUNIXãŠãŒãã£ãªãã£ar
ãŸãã¯Go- cmd / packã®å
éšé¡äŒŒç©ïŒ go tool pack
ïŒã§åäœããŸãã ãã¡ããã2ã€ã®åœ¢åŒã¯éåžžã«ãããã«ç°ãªããŸãã libed25519_dalek_rustgo.a
ã«ã¯ar
ã libed25519_dalek_rustgo.a
ã«ã¯cmd/pack
ã䜿çšããå¿
èŠããããŸãã
ïŒããšãã°ãç§ã®macOSã®ar
ã¯ã BSDèŠåã䜿çšããŠ#1/LEN
ãã¡ã€ã«ãåŒã³åºãããã®ãã¡ã€ã«ã®å
é ã«é·ãLENã®ãã¡ã€ã«åãæ¿å
¥ããŠãæ倧ãã¡ã€ã«é·ã®16ãã€ãããã€ãã¹ããŸããããã¯çŽããããã§ããïŒ
ãããã®2ã€ã®ã©ã€ãã©ãªããªã³ã¯ããããã«ãæãåçŽãªïŒreadïŒcrutchïŒã¡ãœãããäœæããããšããŸããlibed25519_dalek_rustgo.a
ãå¥ã®ãã©ã«ããŒã«æœåºãããã®ãªããžã§ã¯ããedwards25519.a
ãŸãã
edwards25519/edwards25519.a: edwards25519/rustgo.go edwards25519/rustgo.o target/release/libed25519_dalek_rustgo.a go tool compile -N -l -o $@ -p main -pack edwards25519/rustgo.go go tool pack r $@ edwards25519/rustgo.o # from edwards25519/rustgo.s mkdir -p target/release/libed25519_dalek_rustgo && cd target/release/libed25519_dalek_rustgo && \ rm -f *.o && ar xv "$(CURDIR)/target/release/libed25519_dalek_rustgo.a" go tool pack r $@ target/release/libed25519_dalek_rustgo
ããŸããã£ããšãã®é©ããæ³åããŠã¿ãŠãã ããïŒ
.a
ãã¡ã€ã«ãé©åãªå Žæã«çœ®ããŠããã®ããã±ãŒãžã䜿çšããç°¡åãªããã°ã©ã ãäœæããŸãã
package main import ( "bytes" "encoding/hex" "fmt" "testing" "github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519" ) func main() { input, _ := hex.DecodeString("39129b3f7bbd7e17a39679b940018a737fc3bf430fcbc827029e67360aab3707") expected, _ := hex.DecodeString("1cc4789ed5ea69f84ad460941ba0491ff532c1af1fa126733d6c7b62f7ebcbcf") var dst, k [32]byte copy(k[:], input) edwards25519.ScalarBaseMult(&dst, &k) if !bytes.Equal(dst[:], expected) { fmt.Println("rustgo produces a wrong result!") } fmt.Printf("BenchmarkScalarBaseMult\t%v\n", testing.Benchmark(func(b *testing.B) { for i := 0; i < bN; i++ { edwards25519.ScalarBaseMult(&dst, &k) } })) }
go build
å®è¡ãgo build
ïŒ
$ go build -ldflags '-linkmode external -extldflags -lresolv' $ ./ed25519-dalek-rustgo BenchmarkScalarBaseMult 100000 19914 ns/op
ãŸããããã¯ã»ãšãã©åããã ç§ã¯å°ããã³åŒããããªããã°ãªããŸããã§ããã ãã€ããªãã¡ã€ã«ã¯ã libresolv
ãšãªã³ã¯ãããŸã§ã³ã³ãã€ã«ããlibresolv
ã æ£çŽã«èšããšãRustã³ã³ãã€ã©ãŒã¯ãããèšãããšããŸããã ïŒããããRustã³ã³ãã€ã©ãèšãããšã誰ãããŸããŸããŸããïŒïŒ
note: link against the following native artifacts when linking against this static library note: the order and any duplication can be significant on some platforms, and so may need to be preserved note: library: System note: library: resolv note: library: c note: library: m
ã·ã¹ãã ã©ã€ãã©ãªãšã®ãªã³ã¯ã¯ãå
éšãªã³ã«ãŒãšã¯ãã¹ã³ã³ãã€ã«ã§ã¯æ±ºããŠèµ·ãããªããããåé¡ã«ãªããŸã...
ããããã¡ãã£ãšãlib resolveïŒ ãªããããno_std
ããã¢ã»ã³ãã©ã®ããã§ããã¹ãã ããRustã©ã€ãã©ãªã¹ã¿ãã¯ã®ã¿ãDNSåã解決ããããã«æšæºã©ã€ãã©ãªã䜿çšããããšããŠããŸããïŒ
no_stdãšèšã£ã
ããã§ã®åé¡ã¯ãã©ã€ãã©ãªãå®éã«ã¯no_std
ã¯ãªãããšno_std
ã ããã§ãã¹ãŠãèŠãŠãã ããïŒ ã¢ãã±ãŒã¿ãŒã¯å¿
èŠãããŸããã
$ ar t target/release/libed25519_dalek_rustgo.a __.SYMDEF ed25519_dalek_rustgo-742a1d9f1c101d86.0.o ed25519_dalek_rustgo-742a1d9f1c101d86.crate.allocator.o curve25519_dalek-03e3ca0f6d904d88.0.o subtle-cd04b61500f6e56a.0.o std-72653eb2361f5909.0.o panic_unwind-d0b88496572d35a9.0.o unwind-da13b913698118f9.0.o arrayref-2be0c0ff08ae2c7d.0.o digest-f1373d68da35ca45.0.o generic_array-95ca86a62dc11ddc.0.o nodrop-7df18ca19bb4fc21.0.o odds-3bc0ea0bdf8209aa.0.o typenum-a61a9024d805e64e.0.o rand-e0d585156faee9eb.0.o alloc_system-c942637a1f049140.0.o libc-e038d130d15e5dae.0.o alloc-0e789b712308019f.0.o std_unicode-9735142be30abc63.0.o compiler_builtins-8a5da980a34153c7.0.o absvdi2.o absvsi2.o absvti2.o [... snip ...] truncsfhf2.o ucmpdi2.o ucmpti2.o core-9077840c2cc91cbf.0.o
ã ãããã©ã®ããã«ãã¹ãŠã®no_std
ãè¡ãã®ã§ããããïŒ ããã¯å¥ã®åéºã§ããããšãå€æããŸããããçµè«ã ããæžããŸãã
- äŸåé¢ä¿ã
no_std
ã§ãªãno_std
ã no_std
ãã©ã°ã¯no_std
ãŸãã curve25519-dalek
äŸåé¢ä¿ã®1ã€ã«ãã®åé¡ãããã cargo update
ä¿®æ£ãããŸãã no_std
éçã©ã€ãã©ãªïŒã€ãŸããRustå
ã ãã§ãªããå€éšã§äœ¿çšããããã®ã©ã€ãã©ãªïŒã«ãããšãããã¯`no_std
å®è¡å¯èœãã€ããªãäœæããæ¹æ³ã§ããno_std
ãã€ããªã®äœææ¹æ³ã«é¢ããããã¥ã¡ã³ãã¯éåžžã«å°ãªãã§ãã ç§ã¯åºæ¬çã«Rustã«é¢ããå€ãããŒãžã§ã³ã®æ¬ã䜿çšããæçµçã«ã¯lang_itemsã«é¢ãããã®ã»ã¯ã·ã§ã³ãèŠã€ããŸããã ãã®æçš¿ã圹ã«ç«ã¡ãŸããã- éå§ããã«ã¯ããlang_itemsãé¢æ°ãå®çŸ©ããŠã
panic_fmt
ãããªæšæºã©ã€ãã©ãªã«éåžžåãã£ãŠããæ©èœãå®è£
ããå¿
èŠããããŸãã - Rust
compiler-rt
çžåœãããã®ããªãã®ã§ã crate compiler_builtinsïŒ rust-lang / rustïŒ43264 ïŒãã€ã³ããŒãããå¿
èŠããããŸã rust_begin_unwind
, no_mangle
panic_fmt
, ( rust-lang/rust#38281 )memcpy
, , , Rust rlibc
. , nm -u
, .
lib.rs
:
#![no_std] #![feature(lang_items, compiler_builtins_lib, core_intrinsics)] use core::intrinsics; #[allow(private_no_mangle_fns)] #[no_mangle]
, go build
(!!!) macOS.
Linux
Linux .
fmax
, , , :
$ ld -r -o linux.o target/release/libed25519_dalek_rustgo/*.o $ nm -u linux.o U _GLOBAL_OFFSET_TABLE_ U abort U fmax U fmaxf U fmaxl U logb U logbf U logbl U scalbn U scalbnf U scalbnl
, , --gc-sections
, , . , , ( ):
$ go build -ldflags '-extld clang -linkmode external -extldflags -Wl,--gc-sections'
, , Makefile , --gc-sections
? , .a
man- .
.o
, , ld -r --gc-sections -u $SYMBOL
. -r
-u
"", . $SYMBOL
scalar_base_mult
.
macOS? , , , macOS .
$ ld -e _scalar_base_mult target/release/libed25519_dalek_rustgo/*.o Undefined symbols for architecture x86_64: "___assert_rtn", referenced from: _compilerrt_abort_impl in int_util.o "_copysign", referenced from: ___divdc3 in divdc3.o ___muldc3 in muldc3.o "_copysignf", referenced from: ___divsc3 in divsc3.o ___mulsc3 in mulsc3.o "_copysignl", referenced from: ___divxc3 in divxc3.o ___mulxc3 in mulxc3.o "_fmax", referenced from: ___divdc3 in divdc3.o "_fmaxf", referenced from: ___divsc3 in divsc3.o "_fmaxl", referenced from: ___divxc3 in divxc3.o "_logb", referenced from: ___divdc3 in divdc3.o "_logbf", referenced from: ___divsc3 in divsc3.o "_logbl", referenced from: ___divxc3 in divxc3.o "_scalbn", referenced from: ___divdc3 in divdc3.o "_scalbnf", referenced from: ___divsc3 in divsc3.o "_scalbnl", referenced from: ___divxc3 in divxc3.o ld: symbol(s) not found for inferred architecture x86_64 $ ld -e _scalar_base_mult -dead_strip target/release/libed25519_dalek_rustgo/*.o
, , macOS _
, .
, Makefile, :]
edwards25519/edwards25519.a: edwards25519/rustgo.go edwards25519/rustgo.o edwards25519/libed25519_dalek_rustgo.o go tool compile -N -l -o $@ -p main -pack edwards25519/rustgo.go go tool pack r $@ edwards25519/rustgo.o edwards25519/libed25519_dalek_rustgo.o edwards25519/libed25519_dalek_rustgo.o: target/$(TARGET)/release/libed25519_dalek_rustgo.a ifeq ($(shell go env GOOS),darwin) $(LD) -r -o $@ -arch x86_64 -u "_$(SYMBOL)" $^ else $(LD) -r -o $@ --gc-sections -u "$(SYMBOL)" $^ endif
Linux. , , . CALL
Rust .
, - , rustgo, , , . cmd/link ( !), , Go, , //cgo:cgo_import_static
, //cgo:cgo_import_dynamic
.
, , - rustgo , macOS, Linux, .
, .a
, //go:binary-only-package
tar- .a
linux_amd64/darwin_amd64
, :
$ tar tf ed25519-dalek-rustgo_go1.8.3.tar.gz src/github.com/FiloSottile/ed25519-dalek-rustgo/ src/github.com/FiloSottile/ed25519-dalek-rustgo/.gitignore src/github.com/FiloSottile/ed25519-dalek-rustgo/Cargo.lock src/github.com/FiloSottile/ed25519-dalek-rustgo/Cargo.toml src/github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519/ src/github.com/FiloSottile/ed25519-dalek-rustgo/main.go src/github.com/FiloSottile/ed25519-dalek-rustgo/Makefile src/github.com/FiloSottile/ed25519-dalek-rustgo/release.sh src/github.com/FiloSottile/ed25519-dalek-rustgo/src/ src/github.com/FiloSottile/ed25519-dalek-rustgo/target.go src/github.com/FiloSottile/ed25519-dalek-rustgo/src/lib.rs src/github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519/rustgo.go src/github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519/rustgo.s pkg/linux_amd64/github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519.a pkg/darwin_amd64/github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519.a
, , - ( .a
).
, , , Rust -Ctarget-cpu=native
, . ( curve25519-dalek authors ) - Haswell , Haswell:
$ benchstat bench-none.txt bench-haswell.txt name old time/op new time/op delta ScalarBaseMult/rustgo 22.0µs ± 3% 20.2µs ± 2% -8.41% (p=0.001 n=7+6) $ benchstat bench-haswell.txt bench-native.txt name old time/op new time/op delta ScalarBaseMult/rustgo 20.2µs ± 2% 20.1µs ± 2% ~ (p=0.945 n=6+7)
, , Makefile GOOS/GOARCH, Rust, Rust -, - .a
.
: github.com/FiloSottile/ed25519-dalek-rustgo/edwards25519
godoc .
, .
, , rustgo , . , , g
, , , , . Rust .
, morestack
NOSPLIT
, , ( rsp
) , , Rust ( ).
, - "rustgo" , Makefile . Cgo , . go:generate
, -, cargo (-, Go Rust!). FFI- Rust, GoSlice
.
#[repr(C)] struct GoSlice { array: *mut u8, len: i32, cap: i32, }
ãŸãã¯ãGoãŸãã¯Rustã®èª°ããæ¥ãŠãæªæãããåã«ç«ã¡æ¢ãŸãããã«èšããããããŸããã
PSã誰ãããããcgoïŒã»ãã¥ãªãã£ã®ããã®ããããã®æ©èœãæã£ãŠããïŒãŸãã¯çŽç²ãªGoãšæ¯èŒãå§ããåã«ãrustgoã¯ã©ã¡ãã®ä»£ããã«ããªããŸãããããã¯ãæäœæ¥ã§èšè¿°ãããã¢ã»ã³ãã©ãŒé¢æ°ããåçã®ããã©ãŒãã³ã¹ã§ããå®å
šã§èªã¿ããããã®ã«çœ®ãæããããšãæå³ããŠããŸãããããã«è¯ãããšã«ãããã¯æ¥œããå®éšãšããŠæå³ãããŠããŸããã