Skip to content
This repository was archived by the owner on Mar 24, 2026. It is now read-only.

Commit 727203b

Browse files
authored
[ruby/json] Use JSON.generate instead of Object#to_json (#10782)
JSON.generate is faster than calling Object#to_json. ```ruby require 'benchmark/ips' require 'json' Benchmark.ips do |x| x.config(warmup: 2, time: 5) x.report("to_json symbol") do { message: 'Hello, World!' }.to_json end x.report("to_json string") do { 'message' => 'Hello, World!' }.to_json end x.report("JSON.generate symbol") do JSON.generate({ message: 'Hello, World!' }) end x.report("JSON.generate string") do JSON.generate({ 'message' => 'Hello, World!' }) end x.compare! end ``` ``` ruby 3.4.8 (2025-12-17 revision 995b59f666) +PRISM [arm64-darwin24] Warming up -------------------------------------- to_json symbol 330.723k i/100ms to_json string 325.411k i/100ms JSON.generate symbol 490.246k i/100ms JSON.generate string 495.752k i/100ms Calculating ------------------------------------- to_json symbol 3.219M (± 8.2%) i/s (310.65 ns/i) - 16.205M in 5.097780s to_json string 3.250M (± 3.5%) i/s (307.67 ns/i) - 16.271M in 5.012989s JSON.generate symbol 4.966M (± 1.5%) i/s (201.35 ns/i) - 25.003M in 5.035419s JSON.generate string 4.973M (± 2.1%) i/s (201.10 ns/i) - 25.283M in 5.086778s Comparison: JSON.generate string: 4972636.6 i/s JSON.generate symbol: 4966478.7 i/s - same-ish: difference falls within error to_json string: 3250251.2 i/s - 1.53x slower to_json symbol: 3219106.9 i/s - 1.54x slower ```
1 parent 9498712 commit 727203b

12 files changed

Lines changed: 29 additions & 28 deletions

File tree

frameworks/Ruby/hanami/app/actions/db/index.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Index < HelloWorld::Action
1111
def handle(*, response)
1212
world = world_repo.find(random_id)
1313
response.format = :json
14-
response.body = world.to_h.to_json
14+
response.body = JSON.generate(world.to_h)
1515
end
1616

1717
def random_id

frameworks/Ruby/hanami/app/actions/queries/index.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def handle(request, response)
1616
world_repo.find(id)
1717
end
1818
response.format = :json
19-
response.body = worlds.map(&:to_h).to_json
19+
response.body = JSON.generate(worlds.map(&:to_h))
2020
end
2121

2222
private

frameworks/Ruby/hanami/app/actions/updates/index.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ def handle(request, response)
1616
world_repo.update_random_number(id)
1717
end
1818
response.format = :json
19-
response.body = worlds.to_json
19+
response.body = JSON.generate(worlds)
2020
end
2121

2222
private

frameworks/Ruby/hanami/config/routes.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class Routes < Hanami::Routes
99
'Content-Type' => 'application/json',
1010
'Date' => Time.now.httpdate,
1111
},
12-
[{ 'message' => 'Hello, World!' }.to_json]]
12+
[JSON.generate({ 'message' => 'Hello, World!' })]]
1313
end
1414
get "/db", to: "db.index"
1515
get "/queries", to: "queries.index"

frameworks/Ruby/padrino/app/controllers.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
end
99

1010
get '/json', :provides => [:json] do
11-
{message: "Hello, World!"}.to_json
11+
JSON.generate({message: "Hello, World!"})
1212
end
1313

1414
get '/db', :provides => [:json] do
1515
world = ActiveRecord::Base.with_connection do
1616
World.find(rand1).attributes
1717
end
18-
world.to_json
18+
JSON.generate(world)
1919
end
2020

2121
get '/queries', :provides => [:json] do
@@ -24,7 +24,7 @@
2424
World.find(id).attributes
2525
end
2626
end
27-
worlds.to_json
27+
JSON.generate(worlds)
2828
end
2929

3030
get '/fortunes' do
@@ -51,7 +51,7 @@
5151
World.upsert_all(worlds)
5252
end
5353

54-
worlds.to_json
54+
JSON.generate(worlds)
5555
end
5656

5757
get '/plaintext' do

frameworks/Ruby/rack-app/app.rb

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,22 +35,23 @@ def fortunes
3535

3636
get '/json' do
3737
set_headers(JSON_TYPE)
38-
{ message: 'Hello, World!' }.to_json
38+
JSON.generate({ message: 'Hello, World!' })
3939
end
4040

4141
get '/db' do
4242
set_headers(JSON_TYPE)
43-
World.with_pk(rand1).values.to_json
43+
JSON.generate(World.with_pk(rand1).values)
4444
end
4545

4646
get '/queries' do
4747
set_headers(JSON_TYPE)
4848
ids = ALL_IDS.sample(bounded_queries)
49-
DB.synchronize do
49+
worlds = DB.synchronize do
5050
ids.map do |id|
5151
World.with_pk(id).values
5252
end
53-
end.to_json
53+
end
54+
JSON.generate(worlds)
5455
end
5556

5657
get '/fortunes' do

frameworks/Ruby/rack-sequel/hello_world.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -105,19 +105,19 @@ def call(env)
105105
case env['PATH_INFO']
106106
when '/json'
107107
# Test type 1: JSON serialization
108-
respond JSON_TYPE, { message: 'Hello, World!' }.to_json
108+
respond JSON_TYPE, JSON.generate({ message: 'Hello, World!' })
109109
when '/db'
110110
# Test type 2: Single database query
111-
respond JSON_TYPE, db.to_json
111+
respond JSON_TYPE, JSON.generate(db)
112112
when '/queries'
113113
# Test type 3: Multiple database queries
114-
respond JSON_TYPE, queries(env).to_json
114+
respond JSON_TYPE, JSON.generate(queries(env))
115115
when '/fortunes'
116116
# Test type 4: Fortunes
117117
respond HTML_TYPE, fortunes
118118
when '/updates'
119119
# Test type 5: Database updates
120-
respond JSON_TYPE, updates(env).to_json
120+
respond JSON_TYPE, JSON.generate(updates(env))
121121
when '/plaintext'
122122
# Test type 6: Plaintext
123123
respond PLAINTEXT_TYPE, 'Hello, World!'

frameworks/Ruby/rack/hello_world.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -53,22 +53,22 @@ def call(env)
5353
when '/json'
5454
# Test type 1: JSON serialization
5555
respond JSON_TYPE,
56-
{ message: 'Hello, World!' }.to_json
56+
JSON.generate({ message: 'Hello, World!' })
5757
when '/db'
5858
# Test type 2: Single database query
5959
id = random_id
60-
respond JSON_TYPE, $db.with{ _1.select_world(id) }.to_json
60+
respond JSON_TYPE, JSON.generate($db.with{ _1.select_world(id) })
6161
when '/queries'
6262
# Test type 3: Multiple database queries
6363
queries = bounded_queries(env)
64-
respond JSON_TYPE, select_worlds(queries).to_json
64+
respond JSON_TYPE, JSON.generate(select_worlds(queries))
6565
when '/fortunes'
6666
# Test type 4: Fortunes
6767
respond HTML_TYPE, fortunes
6868
when '/updates'
6969
# Test type 5: Database updates
7070
queries = bounded_queries(env)
71-
respond JSON_TYPE, update_worlds(queries).to_json
71+
respond JSON_TYPE, JSON.generate(update_worlds(queries))
7272
when '/plaintext'
7373
# Test type 6: Plaintext
7474
respond PLAINTEXT_TYPE, 'Hello, World!'

frameworks/Ruby/rails/config/routes.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
'Content-Type' => 'application/json',
1010
'Date' => Time.now.httpdate,
1111
},
12-
[{ 'message' => 'Hello, World!' }.to_json]]
12+
[JSON.generate({ 'message' => 'Hello, World!' })]]
1313
end
1414
else
1515
->(env) do
@@ -18,7 +18,7 @@
1818
'Server' => 'Rails',
1919
'Content-Type' => 'application/json'
2020
},
21-
[{ 'message' => 'Hello, World!' }.to_json]]
21+
[JSON.generate({ 'message' => 'Hello, World!' })]]
2222
end
2323
end
2424

frameworks/Ruby/roda-sequel/hello_world.rb

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,13 @@ def rand1
4141
# Test type 1: JSON serialization
4242
r.is "json" do
4343
response[CONTENT_TYPE] = JSON_TYPE
44-
{ message: "Hello, World!" }.to_json
44+
JSON.generate({ message: "Hello, World!" })
4545
end
4646

4747
# Test type 2: Single database query
4848
r.is "db" do
4949
response[CONTENT_TYPE] = JSON_TYPE
50-
World.with_pk(rand1).values.to_json
50+
JSON.generate(World.with_pk(rand1).values)
5151
end
5252

5353
# Test type 3: Multiple database queries
@@ -60,7 +60,7 @@ def rand1
6060
World.with_pk(id).values
6161
end
6262
end
63-
worlds.to_json
63+
JSON.generate(worlds)
6464
end
6565

6666
# Test type 4: Fortunes
@@ -93,7 +93,7 @@ def rand1
9393
end
9494
World.batch_update(worlds)
9595
end
96-
worlds.map!(&:values).to_json
96+
JSON.generate(worlds.map!(&:values))
9797
end
9898

9999
# Test type 6: Plaintext

0 commit comments

Comments
 (0)