Reputation: 655
we are currently developing our first single page application and noticed some unexpected behaviour when it comes to static files.
We set up our endpoint.ex by including our static files using Plug.Static:
plug Plug.Static,
at: "/", from: :app,
only: ~w(js index.html robots.txt)
Our router.ex includes the following routes:
scope "/", App do
pipe_through :browser # Use the default browser stack
get "/*path", PageController, :index
end
The PageController redirects to the static file:
@index "/index.html"
def index(conn, _params) do
redirect(conn, to: @index)
end
We would expect the static files to be loaded once when the server starts. However when we used wrk to test (results below) the performance and noticed that requests to /index.html (the static resource) are only half as fast as requests to any other route that uses the redirect of the PageController.
./wrk -t4 -c200 -d30S --timeout 2000 "http://localhost:4000/index.html"
Running 30s test @ http://localhost:4000/index.html
4 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 46.39ms 31.24ms 443.14ms 95.68%
Req/Sec 1.13k 264.38 1.49k 80.27%
134494 requests in 30.03s, 92.89MB read
Socket errors: connect 0, read 30, write 0, timeout 0
Requests/sec: 4478.30
Transfer/sec: 3.09MB
./wrk -t4 -c200 -d30S --timeout 2000 "http://localhost:4000/anythingelse"
Running 30s test @ http://localhost:4000/indexjhtml
4 threads and 200 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 30.88ms 49.61ms 760.40ms 94.79%
Req/Sec 2.16k 679.55 4.58k 75.39%
256135 requests in 30.08s, 105.08MB read
Requests/sec: 8515.77
Transfer/sec: 3.49MB
We are wondering why the requests are slower accessing the static resource using the direct route compared to other paths that redirect to the static resource.
It seems like the static file get opened multiple times when we expect it to be opened just once.
Maybe someone could explain the static resources to us?
We also (sometimes) get a warning when doing the test for /index.html
13:59:00.247 [warn] Ranch acceptor reducing accept rate: out of file descriptors
Upvotes: 0
Views: 664
Reputation: 222428
We are wondering why the requests are slower accessing the static resource using the direct route compared to other paths that redirect to the static resource.
This is because wrk
does not follow the redirect. This can be verified by calculating the bytes per request from your stats.
/index.html
: 134494 requests in 30.03s, 92.89MB read = ~724 bytes per request
/anythingelse
: 256135 requests in 30.08s, 105.08MB read = ~430 bytes per request
So /anythingelse
is smaller than /index.html
according to wrk
.
The 430 byte response is just the 302 redirect response written by phoenix for redirect(conn, to: "/index.html")
. As you'd expect, just writing a 302 response is faster than reading and writing the contents of the file index.html
.
It seems like the static file get opened multiple times when we expect it to be opened just once.
Files served by Plug.Static
are not read and cached once; they're read from the disk on each request. If you want to store the contents in memory at compile time, you can read the file in your controller and then write it yourself in the action:
@index_html File.read!("path/to/index.html)
def index(conn, _params) do
send_resp(conn, 200, @index_html)
end
Upvotes: 2
Reputation: 121010
In development mode, phoenix makes it easy for you to develop applications by setting watch on the files for live reload. The setting is in config/dev.exs
:
config :your_app, YourApp.Web.Endpoint,
...
watchers: [node: ["node_modules/brunch/bin/brunch", "watch", "--stdin",
cd: Path.expand("../assets", __DIR__)]]
# Watch static and templates for browser reloading.
config :your_app, YourApp.Web.Endpoint,
live_reload: [
patterns: [
~r{priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$},
~r{priv/gettext/.*(po)$},
~r{lib/your_app/web/views/.*(ex)$},
~r{lib/your_app/web/templates/.*(eex)$}
]
]
or similar. Tune this setting up to watch only what you want to be watched.
In both test
and production
environments this flag is obviously not set at all. It seems you also might want to make sure, that wrk
runs in test
environment.
Upvotes: -1