{"id":15594975,"url":"https://github.com/simonneutert/joda","last_synced_at":"2025-06-13T07:04:51.213Z","repository":{"id":64685290,"uuid":"527164239","full_name":"simonneutert/Joda","owner":"simonneutert","description":"JRuby + Roda == Joda 🖖","archived":false,"fork":false,"pushed_at":"2025-05-09T05:28:23.000Z","size":3873,"stargazers_count":7,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-05-09T06:25:14.942Z","etag":null,"topics":["api","jdbc","jruby","jvm","jvm-applications","jvm-languages","puma","roda","router","ruby","sequel"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/simonneutert.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-21T09:47:28.000Z","updated_at":"2025-05-09T05:28:25.000Z","dependencies_parsed_at":"2023-01-29T13:31:55.395Z","dependency_job_id":"7f8fcc6b-50b9-4e0a-84a4-9493550aed6c","html_url":"https://github.com/simonneutert/Joda","commit_stats":null,"previous_names":[],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/simonneutert/Joda","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2FJoda","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2FJoda/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2FJoda/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2FJoda/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/simonneutert","download_url":"https://codeload.github.com/simonneutert/Joda/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/simonneutert%2FJoda/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259599320,"owners_count":22882353,"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":["api","jdbc","jruby","jvm","jvm-applications","jvm-languages","puma","roda","router","ruby","sequel"],"created_at":"2024-10-03T00:42:29.250Z","updated_at":"2025-06-13T07:04:51.188Z","avatar_url":"https://github.com/simonneutert.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Joda 🖖 == JRuby + Roda\n\nAnd here it is 🎉 My template for Ruby's notorious web router [Roda](https://roda.jeremyevans.net) - running on the JVM ([JRuby](https://www.jruby.org))! 🌋\n\nStart the server with `$ rackup`, then benchmark (see below) as unscientifically as possible (but easy as pie), using [HTTPie](https://httpie.io):\n\n_🤫 or for production, sth. like: `$ jruby --server -S bundle exec rackup -o 0 -E production`_\n\n`$ time http :9292/jsondata \u003e/dev/null`  \nsucks 25mb from your server 🧛‍♀️\n\nAdd [rodauth](https://github.com/jeremyevans/rodauth) to have a proper user account management 🤯\n\n## Why though?\n\nI cannot really say why JRuby intriqued me, since I fell in love with Ruby.\nBut, JRuby never felt especially beginner friendly. 😬  \nSomething didn't work. Very tough to google. JDBC what?  \nJava docs?! Java ecosystem?! They do what? How on earth? Cheesus ... 🤢\n\n## This repository is aimed at\n\n- curious Rubyists, struggling to find a use case of getting something up with [JRuby](https://www.jruby.org)\n- those who want get hold of JRuby, without the suspicious feeling that Rails takes care of everything behind the curtains (it's why we love you, Rails, you know that! 😘)\n- People curious of [Roda](https://roda.jeremyevans.net)\n- PORO lovers\n- [Rack](https://github.com/rack/rack) fanboys\n- [Sinatra](https://sinatrarb.com) / [Fastify](https://www.fastify.io) / [FastAPI](https://fastapi.tiangolo.com) / [Gin](https://github.com/gin-gonic/gin)\n- Java people / JVM users ☕️\n- those on a journey, they don't know, they are on: Ruby ➡ JRuby ➡ [Clojure](https://clojure.org/guides/getting_started) ☮️\n\n## Run\n\nYour Java version should be pinned to `11.x` as this is what the CI is running on. MacOS checks for JRuby run on Java v8.\n\nif one of you gets this going on another OS, please submit a PR with some handy notes ✌️\n\n### Docker\n\n- `$ docker build . -t joda`\n- `$ docker run --rm -it -p9292:9292 joda`\n\n#### with jemalloc\n\nFor aarch64 (e.g. Mac M1):\n\n- `$ docker run -ti --env LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2 --rm -p9292:9292`\n\nFor x86_64:\n\n- `$ docker run -ti --env LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libjemalloc.so.2 --rm -p9292:9292`\n\n#### Production\n\n🚀\n\n- `$ docker run -ti --env LD_PRELOAD=/usr/lib/aarch64-linux-gnu/libjemalloc.so.2 --rm -p9292:9292 rackup -o 0 -E production`\n\n\n### MacOS and asdf\n\nplease, see the docs of your [asdf-vm](https://asdf-vm.com) java plugin ([docs of the default java plugin 📖](https://github.com/halcyon/asdf-java#java_home)). It's about JRuby having Java in it's PATH.\n\nThen fire the following commands:\n\n- `$ asdf install java microsoft-17.35.1`\n- `$ asdf reshim`\n- `$ asdf install ruby jruby-9.4.1.0`\n- `$ bundle install -j4`\n- `$ jruby -S rackup`\n\n## Profiling JRuby\n\n`$ jruby --profile.graph -S rackup`\n\n## JVM Options\n\nThis is how you could use it for production:\n`$ jruby -J-Xmx512m --server -S rackup -E production`\n\n- minimum and maximum Java heap size to 512 MB\n- optimization for server ON\n- runs Rack in production mode\n\nor:\n\n`$ jruby -J-Xms2g -J-Xmx2g --server -J-Djruby.thread.pool.enabled=true -S rackup -E production`\n\n## Benchmarks 🥼🧪💻\n\n**FIRST OF ALL** the JVM had some requests before the benchs to warm up a little  \n**BUT** let's be honest the server wasn't fresh and had already other stuff to do  \n**AND** had just 2 cores (but 8 gigs of RAM 😅)  \n**AND** for sure I missed an opportunity for tweaking something  \n**BECAUSE** the JVM still is completely new to me at this point  \n**SO** this is worthless, but some just need to see some numbers\n\nwell, enough whining...\n\n- [ab](https://httpd.apache.org/docs/2.4/programs/ab.html) (comes pre-installed on MacOS)\n- [wrk](https://github.com/wg/wrk) (i.e. `$ brew install wrk`)\n\n### Benchmarking with [ab](https://httpd.apache.org/docs/2.4/programs/ab.html):\n\n`$ ab -n 1000 -c 10 -k -H \"Accept-Encoding: gzip, deflate\" \"https://joda.test.test/hello/world\"`\n\n```bash\nThis is ApacheBench, Version 2.3 \u003c$Revision: 1879490 $\u003e\nCopyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/\nLicensed to The Apache Software Foundation, http://www.apache.org/\n\nBenchmarking joda.test.test (be patient)\n[...shortened...]\n\nServer Software:\nServer Hostname:        joda.test.test\nServer Port:            443\nSSL/TLS Protocol:       TLSv1.2,ECDHE-RSA-CHACHA20-POLY1305,4096,256\nServer Temp Key:        ECDH X25519 253 bits\nTLS Server Name:        joda.test.test\n\nDocument Path:          /hello/world\nDocument Length:        38 bytes\n\nConcurrency Level:      10\nTime taken for tests:   11.268 seconds\nComplete requests:      1000\nFailed requests:        0\nKeep-Alive requests:    0\nTotal transferred:      166000 bytes\nHTML transferred:       38000 bytes\nRequests per second:    88.74 [#/sec] (mean)\nTime per request:       112.685 [ms] (mean)\nTime per request:       11.268 [ms] (mean, across all concurrent requests)\nTransfer rate:          14.39 [Kbytes/sec] received\n\nConnection Times (ms)\n              min  mean[+/-sd] median   max\nConnect:       49   78  14.4     77     137\nProcessing:    12   33  22.0     22     113\nWaiting:       11   23  12.1     17      77\nTotal:         64  111  26.2    105     244\n\nPercentage of the requests served within a certain time (ms)\n  50%    105\n  66%    117\n  75%    126\n  80%    131\n  90%    151\n  95%    164\n  98%    176\n  99%    186\n 100%    244 (longest request)\n```\n\n### Benchmarking with [wrk](https://github.com/wg/wrk):\n\n`$ wrk -t10 -c10 -d30s \"https://joda.test.test/hello/world\"`\n\n```bash\nRunning 30s test @ https://joda.test.test/hello/world\n  10 threads and 10 connections\n  Thread Stats   Avg      Stdev     Max   +/- Stdev\n    Latency    23.21ms   15.14ms  81.68ms   84.52%\n    Req/Sec    46.87     15.47    80.00     62.34%\n  14065 requests in 30.10s, 2.07MB read\nRequests/sec:    467.21\nTransfer/sec:     70.28KB\n```\n\n#### Device\n\n|                       |                                     |\n| --------------------- | ----------------------------------- |\n| Model Name            | MacBook Pro                         |\n| Model Identifier      | MacBookPro18,1                      |\n| Chip                  | Apple M1 Pro                        |\n| Total Number of Cores | 10 (8 performance and 2 efficiency) |\n| Memory                | 16 GB                               |\n\n## Thought Section\n\nEntering this fancy new rabbit hole, here's what didn't work, or may well be served with butter in the future\n\n#### Database\n\nwhen load testing `/jsondata/items` route:\n\n- H2 database is run with `single_threaded: true` and seems to be able to handle higher loads nicely 👏\n  https://sequel.jeremyevans.net/rdoc/files/doc/opening_databases_rdoc.html#label-General+connection+options\n\n- H2 database may crash though, especially without `single_threaded` option, and throw horrifying errors, I propose you use Postgres/MySQL/AnyOtherProperDB for mimicking \"real-life\" server simulation\n\n#### Roda\n\nthere's so much beauty in Roda, so it would be nice to showcase more of it.\n\nI suggest you stumble through the following websites:\n\n- [Roda's Website](https://roda.jeremyevans.net)\n- Federico's and [Avdi](https://avdi.codes)'s Book: [Mastering Roda](https://fiachetti.gitlab.io/mastering-roda/)\n- [Jeremy Evans' Code Lair](https://code.jeremyevans.net/ruby.html) (sequel, rodauth, and many more)\n\n---\n\n#### Credits\n\n- large file json taken from:  \n  https://github.com/json-iterator/test-data/blob/master/large-file.json\n\n- Inspiration sparked the amazing [Ruby for all Podcast](https://www.rubyforall.com/) 👋 You guys rock!\n\n#### SEO Stuff 🤭\n\nTags/Keywords: Ruby, JRuby, Java, Roda, Sequel, JDBC, Puma, REST, API, JSON\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonneutert%2Fjoda","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsimonneutert%2Fjoda","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsimonneutert%2Fjoda/lists"}