{"id":13415564,"url":"https://github.com/godzie44/go-uring","last_synced_at":"2025-04-13T16:40:55.931Z","repository":{"id":43681632,"uuid":"409299415","full_name":"godzie44/go-uring","owner":"godzie44","description":"The `io_uring` library and runtime for GO","archived":false,"fork":false,"pushed_at":"2025-04-09T21:08:03.000Z","size":1353,"stargazers_count":127,"open_issues_count":0,"forks_count":12,"subscribers_count":6,"default_branch":"master","last_synced_at":"2025-04-09T22:21:32.392Z","etag":null,"topics":["go","io-uring","linux"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/godzie44.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-09-22T17:38:43.000Z","updated_at":"2025-04-09T21:08:07.000Z","dependencies_parsed_at":"2022-08-20T23:40:58.133Z","dependency_job_id":null,"html_url":"https://github.com/godzie44/go-uring","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godzie44%2Fgo-uring","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godzie44%2Fgo-uring/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godzie44%2Fgo-uring/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godzie44%2Fgo-uring/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/godzie44","download_url":"https://codeload.github.com/godzie44/go-uring/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248746891,"owners_count":21155342,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["go","io-uring","linux"],"created_at":"2024-07-30T21:00:50.335Z","updated_at":"2025-04-13T16:40:55.905Z","avatar_url":"https://github.com/godzie44.png","language":"Go","funding_links":[],"categories":["Go"],"sub_categories":[],"readme":"## GO-URING\n\nLinux io_uring for GO.\n\nA series of articles about this library and io_uring (RU):\n* [1](https://habr.com/ru/company/itsoft/blog/589389/)\n* [2](https://habr.com/ru/company/itsoft/blog/597745/)\n* [3](https://habr.com/ru/company/itsoft/blog/649161/)\n\n## About\nThis project contains:\n1. [uring](#uring-package) package - low-level io_uring API. This API is similar to [liburing](https://github.com/axboe/liburing) API. In other words - this is a port of [liburing](https://github.com/axboe/liburing).\n2. [reactor](#reactor-package) package - high-level API - implementation of event loop pattern with io_uring.\n3. [net](#net-package) package - this is an implementation of net.Listener and net.Conn interfaces with io_uring.\n4. Examples and benchmarks:\n   * [Plain echo server](#plain-tcp-echo-server)\n   * [GO-style echo server](#go-style-tcp-echo-server) (multi thread/goroutine)\n   * [HTTP server](#http-server)\n\n## URING package\n\nPackage uring is a port of liburing. It provides low-level functionality for working with io_uring.\nExample of usage:\n\n- read file:\n```GO\npackage main\n\nimport (\n   \"fmt\"\n   \"github.com/godzie44/go-uring/uring\"\n   \"os\"\n)\n\nfunc main() {\n   ring, err := uring.New(8)\n   noErr(err)\n   defer ring.Close()\n\n   // open file and init read buffers\n   file, err := os.Open(\"./go.mod\")\n   noErr(err)\n   stat, _ := file.Stat()\n   buff := make([]byte, stat.Size())\n\n   // add Read operation to SQ queue\n   err = ring.QueueSQE(uring.Read(file.Fd(), buff, 0), 0, 0)\n   noErr(err)\n\n   // submit all SQ new entries\n   _, err = ring.Submit()\n   noErr(err)\n\n   // wait until data is reading into buffer\n   cqe, err := ring.WaitCQEvents(1)\n   noErr(err)\n\n   noErr(cqe.Error()) //check read error\n\n   fmt.Printf(\"read %d bytes, read result: \\n%s\", cqe.Res, string(buff))\n\n   // dequeue CQ\n   ring.SeenCQE(cqe)\n}\n```\n\n- accept incoming connections:\n```GO\npackage main\n\nimport (\n   \"fmt\"\n   \"github.com/godzie44/go-uring/uring\"\n   \"syscall\"\n)\n\nfunc main() {\n   // create io_uring instance\n   ring, err := uring.New(8)\n   noErr(err)\n   defer ring.Close()\n\n   // create server socket\n   socketFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)\n   noErr(err)\n   defer syscall.Close(socketFd)\n\n   addr := syscall.SockaddrInet4{Port: 8081}\n   noErr(syscall.Bind(socketFd, \u0026addr))\n   noErr(syscall.Listen(socketFd, syscall.SOMAXCONN))\n\n   for {\n      // add Accept operation to SQ queue\n      err = ring.QueueSQE(uring.Accept(uintptr(socketFd), 0), 0, 0)\n      noErr(err)\n\n      // submit all SQ new entries\n      _, err = ring.Submit()\n      noErr(err)\n\n      // wait until new client connection is accepted\n      cqe, err := ring.WaitCQEvents(1)\n      noErr(err)\n\n      //check accept error\n      noErr(cqe.Error())\n\n      // handle client socket, socket descriptor now in cqe.Res field\n      fmt.Printf(\"socket %d connected\\n\", cqe.Res)\n\n      // dequeue CQ\n      ring.SeenCQE(cqe)\n   }\n}\n```\n\n- Look more examples in uring package tests\n\n#### Release/Acquire semantic\n\nModel of GO atomic is more strict than atomics using in liburing. Currently, there is no public description of memory model for GO atomics, \nbut with these articles ([1](https://research.swtch.com/gomm), [2](https://github.com/golang/go/issues/5045)), we know that the implementation of GO atomics is the same as default (seq_cst) atomics in C/C++. \nBut liburing use less strict semantic (explained [here](https://kernel.dk/io_uring.pdf)) - similar memory_order_acquire/memory_order_release semantic in C/C++ memory model. Certainly, we can use\nGO atomics as is (because of strict semantic), but this entails some overhead costs.\n\nThis lib provides experimental and totally unsafe realization of memory_order_acquire/memory_order_release atomics for amd64 arch, you can enable it\nby adding build tag amd64_atomic. It is based on the fact that MOV instructions are enough to implement memory_order_acquire/memory_order_release on the amd64 architecture ([link](https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html)). For example:\n\n```sh\n  go test -v -tags amd64_atomic ./...\n```\n\nThis can give about 1%-3% performance gain.\n\n## REACTOR package \n\nReactor - is event loop implemented with io_uring. Currently, there are two reactors in this package:\n1. Reactor - generic event loop, give a possibility to work with all io_uring operations.\n2. NetReactor - event loop optimized for work with network operations on sockets.\n\nExample of usage:\n- read file:\n```GO\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/godzie44/go-uring/reactor\"\n\t\"github.com/godzie44/go-uring/uring\"\n\t\"os\"\n\t\"os/signal\"\n)\n\nfunc main() {\n\tring, err := uring.New(8)\n\tnoErr(err)\n\n\t// create and start reactor\n\trea, err := reactor.New([]*uring.Ring{ring})\n\tnoErr(err)\n\tctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)\n\tgo func() {\n\t\trea.Run(ctx)\n\t}()\n\n\t// open file and init read buffers\n\tfile, err := os.Open(\"./go.mod\")\n\tnoErr(err)\n\tstat, _ := file.Stat()\n\tbuff := make([]byte, stat.Size())\n\n\t// queue read operation, result CQE will be handled by callback func\n\top := uring.Read(file.Fd(), buff, 0)\n\trea.Queue(op, func(event uring.CQEvent) {\n\t\tnoErr(event.Error()) //check read error\n\t\tfmt.Printf(\"read %d bytes, read result: \\n%s\", event.Res, string(buff))\n\t\tcancel()\n\t})\n\n\t\u003c-ctx.Done()\n}\n```\n\n- accept incoming connections:\n```GO\npackage main\n\nimport (\n\t\"context\"\n\t\"fmt\"\n\t\"github.com/godzie44/go-uring/reactor\"\n\t\"github.com/godzie44/go-uring/uring\"\n\t\"syscall\"\n)\n\nfunc main() {\n\tring, err := uring.New(8)\n\tnoErr(err)\n\n\t// create and start net-reactor\n\trea, err := reactor.NewNet([]*uring.Ring{ring})\n\tnoErr(err)\n\tgo func() {\n\t\trea.Run(context.Background())\n\t}()\n\n\t// create server socket\n\tsocketFd, err := syscall.Socket(syscall.AF_INET, syscall.SOCK_STREAM, 0)\n\tnoErr(err)\n\tdefer syscall.Close(socketFd)\n\taddr := syscall.SockaddrInet4{Port: 8081}\n\tnoErr(syscall.Bind(socketFd, \u0026addr))\n\tnoErr(syscall.Listen(socketFd, syscall.SOMAXCONN))\n\n\tacceptChan := make(chan int32)\n\tfor {\n\t\t// queue accept operation, result CQE will be handled by callback func\n\t\top := uring.Accept(uintptr(socketFd), 0)\n\t\trea.Queue(op, func(event uring.CQEvent) {\n\t\t\tnoErr(event.Error()) //check accept error\n\t\t\tacceptChan \u003c- event.Res\n\t\t})\n\n\t\tfmt.Printf(\"socket %d connected\\n\", \u003c-acceptChan)\n\t}\n}\n```\n- Look more examples in reactor package tests\n\n## NET package\n\nThis is the implementation of net.Listener and net.Conn interfaces. Uses NetReactor inside. Please check the example of [HTTP server](#http-server) and [multi thread TCP echo-server](#go-style-tcp-echo-server) to familiarize yourself with it.\n\n## Examples and benchmarks\n\n#### Plain TCP echo-server\n\nSingle thread echo-server (listens on a specific TCP port and as soon as any data arrives at this port, it immediately forwards it back to the sender) implemented with go-uring.\nUseful for compare GO go-uring lib realization with liburing realization.\nSee [source code](https://github.com/godzie44/go-uring/blob/master/example/echo-server/main.go) and [benchmarks](https://github.com/godzie44/go-uring/blob/master/example/echo-server/benchmark.md) for familiarization.\n\n#### GO-style TCP echo-server\n\nEcho-server (listens on a specific TCP port and as soon as any data arrives at this port, it immediately forwards it back to the sender) implemented with go-uring and reactor packages. \nRealization similar with realization of echo-server with net/http package (benchmarks attached).\nSee [source code](https://github.com/godzie44/go-uring/blob/master/example/echo-server-multi-thread/main.go) and [benchmarks](https://github.com/godzie44/go-uring/blob/master/example/echo-server-multi-thread/Benchmark.md) for familiarization.\n\n#### HTTP server\n\nExample of HTTP-server implemented with io_uring. [Sources](https://github.com/godzie44/go-uring/blob/master/example/http-server/main.go).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodzie44%2Fgo-uring","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgodzie44%2Fgo-uring","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodzie44%2Fgo-uring/lists"}