'Programming > rust' 카테고리의 다른 글
rust visibility and privacy (0) | 2023.05.25 |
---|---|
rust 소유권 (0) | 2023.05.25 |
c에서 rust 호출하기 (0) | 2023.05.11 |
rust 실행파일 (0) | 2023.05.11 |
rust if문 (0) | 2023.05.11 |
rust visibility and privacy (0) | 2023.05.25 |
---|---|
rust 소유권 (0) | 2023.05.25 |
c에서 rust 호출하기 (0) | 2023.05.11 |
rust 실행파일 (0) | 2023.05.11 |
rust if문 (0) | 2023.05.11 |
유튜브에서 노마드 코더의 추천영상에 webGPU라는게 떠서 찾아보니
겁나 따끈한(고작 8일 지난..) 표준이다.
WebGPU W3C Working Draft, 10 May 2023 |
[링크 : https://www.w3.org/TR/webgpu/]
[링크 : https://codelabs.developers.google.com/your-first-webgpu-app?hl=ko#0]
크롬94 베타 부터 webgpu 지원이 시작되었다는데(일단 글은 2021.09.11)
[링크 : https://www.clien.net/service/board/park/16489505]
webGL을 물리치고 대세가 될지 아니면 병행하게 될지 미래가 궁금해진다.
윈10 + 크롬 버전 113.0.5672.93(공식 빌드) (64비트)
ubuntu 18.04 + 버전 113.0.5672.126(공식 빌드) (64비트)
[링크 : https://webgpu.github.io/webgpu-samples/samples/shadowMapping]
+
리눅스에서는 webGPU가 disable인데.. 이걸 어떻게 켤 수 있으려나?
chrome://gpu/ |
[링크 : https://discourse.threejs.org/t/webgpu-example-not-working-in-ubuntu-20-04/40484]
javascript 배열을파일로 저장하기 (0) | 2023.08.02 |
---|---|
Canvas2D: Multiple readback operations using getImageData (0) | 2023.07.24 |
chart.js log 스케일 (0) | 2023.03.31 |
chatGPT님 가라사대 Server-Sent Events (SSE) (0) | 2023.03.15 |
JWT 로그인 예제 (0) | 2022.08.24 |
채널의 경우 1개로 해두면 하나가 들어갈 때 까지 해당 위치에서 블로킹 된다.
아래 예제는 받는 부분을 삭제했는데 그렇기에 채널을 통해 전송은 되지만 수신하지 않아 비워지지 않기 때문에
one을 출력하지 못하고 멈춰있는 것을 확인할 수 있다.
package main import ( f "fmt" "time" ) func main() { f.Println("select") c1 := make(chan string) c2 := make(chan string) go func() { time.Sleep(time.Second * 1) f.Println("---") c1 <- "one" f.Println("one") c1 <- "two" f.Println("two") c1 <- "three" f.Println("three") c1 <- "four" f.Println("four") }() go func() { time.Sleep(time.Second * 2) c2 <- "fifth" }() for i := 0; i < 10000000000; i++ { time.Sleep(time.Second) } } |
$ go run go.go select --- ^Csignal: interrupt |
다만, make를 통해 채널 버퍼를 n개로 만들어 두면, 넣을 수 있는 동안은 넣고 블로킹 되지 않고 넘어갈 수 있다.
package main import ( f "fmt" "time" ) func main() { f.Println("select") c1 := make(chan string, 4) c2 := make(chan string) go func() { time.Sleep(time.Second * 1) f.Println("---") c1 <- "one" f.Println("one") c1 <- "two" f.Println("two") c1 <- "three" f.Println("three") c1 <- "four" f.Println("four") }() go func() { time.Sleep(time.Second * 2) c2 <- "fifth" }() for i := 0; i < 10000000000; i++ { time.Sleep(time.Second) } } |
$ go run go.go select --- one two three four ^Csignal: interrupt |
golang echo server middleware (0) | 2023.05.24 |
---|---|
golang 동시성 (0) | 2023.05.24 |
golang switch, select (0) | 2023.05.16 |
golang uds (0) | 2023.05.16 |
golang mutex (sync) (0) | 2023.05.16 |
golang switch는 신형 언어에 확장되서 그런가 꽤나 만능이다.
특이하게 조건식도 가능하고, 케이스 리스트도 된다.(c#에서 얼핏 봤던 느낌..)
package main import ( "fmt" "time" ) func main() { t := time.Now() switch { case t.Hour() < 12: fmt.Println("Good morning!") case t.Hour() < 17: fmt.Println("Good afternoon.") default: fmt.Println("Good evening.") } } |
[링크 :https://go.dev/tour/flowcontrol/11]
func WhiteSpace(c rune) bool { switch c { case ' ', '\t', '\n', '\f', '\r': return true } return false } |
[링크 : https://hamait.tistory.com/1017]
아무튼 select는 channel 처리에 좀더 특화된 구문으로 생긴것 자체는 switch - case와 동일하게 작성된다.
다만, 동시에 여러개가 들어왔을 경우 랜덤하게 실행된다고 한다.
(생각이 꼬였는지 동시에 들어오면 가장 위에꺼 부터 실행되어야 하는거 아냐? 싶은데 동시성이니까 랜덤하게 처리되는건가..)
The select statement lets a goroutine wait on multiple communication operations. A select blocks until one of its cases can run, then it executes that case. It chooses one at random if multiple are ready. |
package main import "fmt" func fibonacci(c, quit chan int) { x, y := 0, 1 for { select { case c <- x: x, y = y, x+y case <-quit: fmt.Println("quit") return } } } func main() { c := make(chan int) quit := make(chan int) go func() { for i := 0; i < 10; i++ { fmt.Println(<-c) } quit <- 0 }() fibonacci(c, quit) } |
[링크 : https://go.dev/tour/concurrency/5]
[링크 : https://edu.goorm.io/learn/lecture/2010/한-눈에-끝내는-고랭-기초/lesson/382961/채널-select문]
golang 동시성 (0) | 2023.05.24 |
---|---|
golang 고루틴과 채널 (0) | 2023.05.16 |
golang uds (0) | 2023.05.16 |
golang mutex (sync) (0) | 2023.05.16 |
go 포맷터 (0) | 2023.05.11 |
쓸만하려나?
server | client |
package main import ( "fmt" "log" "os" "path/filepath" "time" "github.com/google/uuid" "github.com/johnsiilver/golib/ipc/uds" ) func main() { socketAddr := filepath.Join(os.TempDir(), uuid.New().String()) cred, _, err := uds.Current() if err != nil { panic(err) } // This will set the socket file to have a uid and gid of whatever the // current user is. 0770 will be set for the file permissions (though on some // systems the sticky bit gets set, resulting in 1770. serv, err := uds.NewServer(socketAddr, cred.UID.Int(), cred.GID.Int(), 0770) if err != nil { panic(err) } fmt.Println("Listening on socket: ", socketAddr) // This listens for a client connecting and returns the connection object. for conn := range serv.Conn() { conn := conn // We spinoff handling of this connection to its own goroutine and // go back to listening for another connection. go func() { // We are checking the client's user ID to make sure its the same // user ID or we reject it. Cred objects give you the user's // uid/gid/pid for filtering. if conn.Cred.UID.Int() != cred.UID.Int() { log.Printf("unauthorized user uid %d attempted a connection", conn.Cred.UID.Int()) conn.Close() return } // Write to the stream every 10 seconds until the connection closes. for { if _, err := conn.Write([]byte(fmt.Sprintf("%s\n", time.Now().UTC()))); err != nil { conn.Close() } time.Sleep(10 * time.Second) } }() } } |
package main import ( "flag" "fmt" "io" "os" "github.com/johnsiilver/golib/ipc/uds" ) var ( addr = flag.String("addr", "", "The path to the unix socket to dial") ) func main() { flag.Parse() if *addr == "" { fmt.Println("did not pass --addr") os.Exit(1) } cred, _, err := uds.Current() if err != nil { panic(err) } // Connects to the server at socketAddr that must have the file uid/gid of // our current user and one of the os.FileMode specified. client, err := uds.NewClient(*addr, cred.UID.Int(), cred.GID.Int(), []os.FileMode{0770, 1770}) if err != nil { fmt.Println(err) os.Exit(1) } // client implements io.ReadWriteCloser and this will print to the screen // whatever the server sends until the connection is closed. io.Copy(os.Stdout, client) } |
[링크 : https://github.com/johnsiilver/golib/blob/v1.1.2/ipc/uds/example/server/server.go]
[링크 : https://github.com/johnsiilver/golib/blob/v1.1.2/ipc/uds/example/client/client.go]
[링크 : https://pkg.go.dev/github.com/johnsiilver/golib/ipc/uds]
golang 고루틴과 채널 (0) | 2023.05.16 |
---|---|
golang switch, select (0) | 2023.05.16 |
golang mutex (sync) (0) | 2023.05.16 |
go 포맷터 (0) | 2023.05.11 |
golang echo directory listing (0) | 2023.05.08 |
package main import ( "fmt" "sync" "time" ) // SafeCounter is safe to use concurrently. type SafeCounter struct { mu sync.Mutex v map[string]int } // Inc increments the counter for the given key. func (c *SafeCounter) Inc(key string) { c.mu.Lock() // Lock so only one goroutine at a time can access the map c.v. c.v[key]++ c.mu.Unlock() } // Value returns the current value of the counter for the given key. func (c *SafeCounter) Value(key string) int { c.mu.Lock() // Lock so only one goroutine at a time can access the map c.v. defer c.mu.Unlock() return c.v[key] } func main() { c := SafeCounter{v: make(map[string]int)} for i := 0; i < 1000; i++ { go c.Inc("somekey") } time.Sleep(time.Second) fmt.Println(c.Value("somekey")) } |
[링크 : https://go.dev/tour/concurrency/9]
func (*Mutex) Lock ¶ func (m *Mutex) Lock() Lock locks m. If the lock is already in use, the calling goroutine blocks until the mutex is available. func (*Mutex) TryLock ¶ added in go1.18 func (m *Mutex) TryLock() bool TryLock tries to lock m and reports whether it succeeded. Note that while correct uses of TryLock do exist, they are rare, and use of TryLock is often a sign of a deeper problem in a particular use of mutexes. func (*Mutex) Unlock ¶ func (m *Mutex) Unlock() Unlock unlocks m. It is a run-time error if m is not locked on entry to Unlock. A locked Mutex is not associated with a particular goroutine. It is allowed for one goroutine to lock a Mutex and then arrange for another goroutine to unlock it. |
[링크 : https://pkg.go.dev/sync#Mutex.Lock]
[링크 : https://mingrammer.com/gobyexample/mutexes/]
[링크 : https://www.joinc.co.kr/w/GoLang/example/mutexex]
[링크 : https://pyrasis.com/book/GoForTheReallyImpatient/Unit35]
golang switch, select (0) | 2023.05.16 |
---|---|
golang uds (0) | 2023.05.16 |
go 포맷터 (0) | 2023.05.11 |
golang echo directory listing (0) | 2023.05.08 |
golang websocket binary (0) | 2023.03.28 |
go 에는 자체적으로 포맷터가 들어있다.
획일화 되서 나쁘다고 해야하나.. 좋다고 해야하나.. 참 미묘~
To format your code, you can use the gofmt tool directly: gofmt -w yourcode.go Or you can use the “go fmt” command: go fmt path/to/your/package |
[링크 : https://go.dev/blog/gofmt]
golang uds (0) | 2023.05.16 |
---|---|
golang mutex (sync) (0) | 2023.05.16 |
golang echo directory listing (0) | 2023.05.08 |
golang websocket binary (0) | 2023.03.28 |
golang 크로스 컴파일 GOARM GOARCH (0) | 2023.02.03 |
no_mangle을 설정하면 c에서 사용가능한 함수로 빌드 되는 듯.
Every function in your Rust-ffi API needs to have a corresponding header function. #[no_mangle] pub extern "C" fn rust_function() {} would then become void rust_function(); |
[링크 : https://docs.rust-embedded.org/book/interoperability/rust-with-c.html]
[링크 : https://dev.to/dandyvica/how-to-call-rust-functions-from-c-on-linux-h37]
mangle.. mangle이면 cpp이랑 좀 더 용이하게 붙을 느낌인데..?
$ readelf -a main | grep demangle 387: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 393: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 394: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 395: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 400: 000000000002fc20 320 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v010H 401: 000000000002fd60 152 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v06Pa 402: 000000000002fe00 181 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v06Pa 403: 000000000002fec0 202 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v06Pa 404: 000000000002ff90 85 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v06Pa 405: 000000000002fff0 471 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v06Pa 406: 00000000000301d0 79 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 407: 0000000000030220 411 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 408: 00000000000303c0 411 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 409: 0000000000032a00 1868 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 410: 0000000000030560 396 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 411: 0000000000031c00 1282 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 412: 00000000000306f0 354 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 413: 0000000000030860 241 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 414: 0000000000030960 748 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 415: 0000000000032800 509 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 416: 0000000000030c50 514 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 417: 0000000000032110 1138 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 418: 0000000000030e60 152 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 419: 0000000000030f00 159 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 420: 0000000000030fa0 666 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 421: 0000000000031240 147 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 422: 0000000000031af0 260 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 423: 00000000000312e0 164 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 424: 0000000000032590 610 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 425: 0000000000033150 487 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 426: 0000000000033340 720 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 427: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 429: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 430: 0000000000000000 0 FILE LOCAL DEFAULT ABS rustc_demangle.9c38528e-c 492: 000000000002f460 635 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v08de 624: 0000000000033620 802 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle6legac 654: 0000000000031390 1878 FUNC LOCAL DEFAULT 14 _ZN14rustc_demangle2v07Pr 758: 000000000002ea40 395 FUNC GLOBAL DEFAULT 14 _ZN63_$LT$rustc_demangle. 848: 000000000002e330 1695 FUNC GLOBAL DEFAULT 14 _ZN14rustc_demangle8deman 956: 0000000000033950 2970 FUNC GLOBAL DEFAULT 14 _ZN71_$LT$rustc_demangle. 1021: 000000000002f6e0 1332 FUNC GLOBAL DEFAULT 14 _ZN64_$LT$rustc_demangle. 1090: 000000000002ea30 9 FUNC GLOBAL DEFAULT 14 _ZN14rustc_demangle8Deman 1278: 000000000002e9d0 82 FUNC GLOBAL DEFAULT 14 _ZN14rustc_demangle12try_ 1303: 000000000002ebd0 21 FUNC GLOBAL DEFAULT 14 _ZN71_$LT$rustc_demangle. |
rust 소유권 (0) | 2023.05.25 |
---|---|
rust was (0) | 2023.05.20 |
rust 실행파일 (0) | 2023.05.11 |
rust if문 (0) | 2023.05.11 |
rust rustup doc (0) | 2023.05.10 |
dynamic link 이고
$ file * main: ELF 64-bit LSB shared object, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=989d3d9b6419e9e16be59fe589ddda8c631c30f0, with debug_info, not stripped main.rs: C source, ASCII text |
링크 된걸 보면 c 프로그램과 별 차이가 없긴 한데
$ ldd main linux-vdso.so.1 (0x00007ffe605de000) libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007efd04cd8000) librt.so.1 => /lib/x86_64-linux-gnu/librt.so.1 (0x00007efd04ad0000) libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007efd048b1000) libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007efd046ad000) libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007efd042bc000) /lib64/ld-linux-x86-64.so.2 (0x00007efd05142000) |
실행 파일 크기가 미친듯이 크다.
golang 처럼 rust 라이브러리 자체는 static으로 link 한건가?
$ ls -alh 합계 12M drwxrwxr-x 2 user user 4.0K 5월 11 10:06 . drwxrwxr-x 24 user user 4.0K 5월 11 10:05 .. -rwxrwxr-x 1 user user 12M 5월 11 10:06 main -rw-rw-r-- 1 user user 148 5월 11 10:06 main.rs |
rust was (0) | 2023.05.20 |
---|---|
c에서 rust 호출하기 (0) | 2023.05.11 |
rust if문 (0) | 2023.05.11 |
rust rustup doc (0) | 2023.05.10 |
rust cargo new를 통한 프로젝트 생성 (0) | 2023.05.09 |
golang과 비슷한데
그럼에도 불구하고 최소한 condition 부분의 괄호를 경로를 띄우지 error는 아니고
중괄호 위치는 마음대로 설정할 수 있다.
$ cat main.rs fn main() { let number = 3; if (number < 5) { println!("condition was true"); } else { println!("condition was false"); } } |
$ rustc main.rs warning: unnecessary parentheses around `if` condition --> main.rs:5:6 | 5 | if (number < 5) | ^ ^ | = note: `#[warn(unused_parens)]` on by default help: remove these parentheses | 5 - if (number < 5) 5 + if number < 5 | warning: 1 warning emitted |
[링크 : https://doc.rust-lang.org/book/ch03-05-control-flow.html]
c에서 rust 호출하기 (0) | 2023.05.11 |
---|---|
rust 실행파일 (0) | 2023.05.11 |
rust rustup doc (0) | 2023.05.10 |
rust cargo new를 통한 프로젝트 생성 (0) | 2023.05.09 |
rust 와 main.rs (0) | 2023.05.09 |