Skip to content

Comments

feat: basic etag handling for tile serving#1834

Merged
CommanderStorm merged 12 commits intomaplibre:mainfrom
CommanderStorm:basic-etag-handling
May 20, 2025
Merged

feat: basic etag handling for tile serving#1834
CommanderStorm merged 12 commits intomaplibre:mainfrom
CommanderStorm:basic-etag-handling

Conversation

@CommanderStorm
Copy link
Member

@CommanderStorm CommanderStorm commented May 19, 2025

This PR adds basic etag handling to the tile serving.

I am currently using an okay hash function for this.
There are better ones like gxhash, but for compatability with the mbtiles-crate, using xxhash is likely also fine. Also, xxhash does not require SIMD.

benchmarks (click to expand)

this branch main
oha --latency-correction -z 5s --no-tui http://localhost:3000/function_zxy_query/18/235085/122323 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/function_zxy_query/18/235085/122323
Summary:
  Success rate: 100.00%
  Total:        60.0012 secs
  Slowest:      0.0102 secs
  Fastest:      0.0000 secs
  Average:      0.0003 secs
  Requests/sec: 165899.5459

  Total data:   1.39 GiB
  Size/request: 150 B
  Size/sec:     23.73 MiB

Response time histogram:
  0.000 [1]       |
  0.001 [9880415] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.002 [71916]   |
  0.003 [1465]    |
  0.004 [255]     |
  0.005 [70]      |
  0.006 [19]      |
  0.007 [9]       |
  0.008 [1]       |
  0.009 [8]       |
  0.010 [9]       |

Response time distribution:
  10.00% in 0.0001 secs
  25.00% in 0.0002 secs
  50.00% in 0.0003 secs
  75.00% in 0.0004 secs
  90.00% in 0.0005 secs
  95.00% in 0.0007 secs
  99.00% in 0.0010 secs
  99.90% in 0.0015 secs
  99.99% in 0.0023 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0013 secs, 0.0004 secs, 0.0025 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0020 secs

Status code distribution:
  [200] 9954168 responses

Error distribution:
  [4] aborted due to deadline
oha --latency-correction -z 5s --no-tui http://localhost:3000/png/0/0/0 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/png/0/0/0
Summary:
  Success rate: 100.00%
  Total:        60.0012 secs
  Slowest:      0.0151 secs
  Fastest:      0.0001 secs
  Average:      0.0011 secs
  Requests/sec: 45705.5820

  Total data:   464.62 GiB
  Size/request: 177.65 KiB
  Size/sec:     7.74 GiB

Response time histogram:
  0.000 [1]       |
  0.002 [2266044] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.003 [380190]  |■■■■■
  0.005 [80469]   |■
  0.006 [12719]   |
  0.008 [2346]    |
  0.009 [465]     |
  0.011 [104]     |
  0.012 [22]      |
  0.014 [4]       |
  0.015 [1]       |

Response time distribution:
  10.00% in 0.0004 secs
  25.00% in 0.0005 secs
  50.00% in 0.0008 secs
  75.00% in 0.0013 secs
  90.00% in 0.0022 secs
  95.00% in 0.0028 secs
  99.00% in 0.0041 secs
  99.90% in 0.0062 secs
  99.99% in 0.0083 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0012 secs, 0.0001 secs, 0.0025 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0024 secs

Status code distribution:
  [200] 2742365 responses

Error distribution:
  [25] aborted due to deadline
oha --latency-correction -z 5s --no-tui http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0
Summary:
  Success rate: 100.00%
  Total:        60.0007 secs
  Slowest:      0.0131 secs
  Fastest:      0.0000 secs
  Average:      0.0003 secs
  Requests/sec: 196864.3927

  Total data:   202.46 GiB
  Size/request: 17.97 KiB
  Size/sec:     3.37 GiB

Response time histogram:
  0.000 [1]        |
  0.001 [11796962] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.003 [14261]    |
  0.004 [451]      |
  0.005 [142]      |
  0.007 [80]       |
  0.008 [14]       |
  0.009 [69]       |
  0.010 [3]        |
  0.012 [3]        |
  0.013 [2]        |

Response time distribution:
  10.00% in 0.0001 secs
  25.00% in 0.0002 secs
  50.00% in 0.0002 secs
  75.00% in 0.0003 secs
  90.00% in 0.0004 secs
  95.00% in 0.0005 secs
  99.00% in 0.0008 secs
  99.90% in 0.0014 secs
  99.99% in 0.0024 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0011 secs, 0.0001 secs, 0.0036 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0032 secs

Status code distribution:
  [200] 11811988 responses

Error distribution:
  [8] aborted due to deadline
oha --latency-correction -z 5s --no-tui http://localhost:3000/function_zxy_query/18/235085/122323 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/function_zxy_query/18/235085/122323
Summary:
  Success rate: 100.00%
  Total:        60.0007 secs
  Slowest:      0.0081 secs
  Fastest:      0.0000 secs
  Average:      0.0003 secs
  Requests/sec: 169325.5218

  Total data:   1.42 GiB
  Size/request: 150 B
  Size/sec:     24.22 MiB

Response time histogram:
  0.000 [1]       |
  0.001 [9968313] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.002 [185441]  |
  0.002 [5144]    |
  0.003 [465]     |
  0.004 [130]     |
  0.005 [127]     |
  0.006 [23]      |
  0.006 [7]       |
  0.007 [0]       |
  0.008 [4]       |

Response time distribution:
  10.00% in 0.0001 secs
  25.00% in 0.0002 secs
  50.00% in 0.0002 secs
  75.00% in 0.0003 secs
  90.00% in 0.0005 secs
  95.00% in 0.0007 secs
  99.00% in 0.0010 secs
  99.90% in 0.0015 secs
  99.99% in 0.0023 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0009 secs, 0.0001 secs, 0.0019 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0017 secs

Status code distribution:
  [200] 10159655 responses

Error distribution:
  [1] aborted due to deadline
oha --latency-correction -z 5s --no-tui http://localhost:3000/png/0/0/0 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/png/0/0/0
Summary:
  Success rate: 100.00%
  Total:        60.0016 secs
  Slowest:      0.0136 secs
  Fastest:      0.0001 secs
  Average:      0.0011 secs
  Requests/sec: 47257.0141

  Total data:   480.40 GiB
  Size/request: 177.65 KiB
  Size/sec:     8.01 GiB

Response time histogram:
  0.000 [1]       |
  0.001 [2247759] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.003 [474646]  |■■■■■■
  0.004 [94111]   |■
  0.005 [15154]   |
  0.007 [2944]    |
  0.008 [641]     |
  0.010 [159]     |
  0.011 [39]      |
  0.012 [9]       |
  0.014 [8]       |

Response time distribution:
  10.00% in 0.0004 secs
  25.00% in 0.0005 secs
  50.00% in 0.0009 secs
  75.00% in 0.0013 secs
  90.00% in 0.0020 secs
  95.00% in 0.0026 secs
  99.00% in 0.0038 secs
  99.90% in 0.0058 secs
  99.99% in 0.0079 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0008 secs, 0.0001 secs, 0.0028 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0020 secs

Status code distribution:
  [200] 2835471 responses

Error distribution:
  [26] aborted due to deadline
oha --latency-correction -z 5s --no-tui http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0 > /dev/null
oha --latency-correction -z 60s         http://localhost:3000/stamen_toner__raster_CC-BY-ODbL_z3/0/0/0
Summary:
  Success rate: 100.00%
  Total:        60.0013 secs
  Slowest:      0.0282 secs
  Fastest:      0.0000 secs
  Average:      0.0002 secs
  Requests/sec: 205800.0158

  Total data:   211.65 GiB
  Size/request: 17.97 KiB
  Size/sec:     3.53 GiB

Response time histogram:
  0.000 [1]        |
  0.003 [12346951] |■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■■
  0.006 [764]      |
  0.008 [282]      |
  0.011 [162]      |
  0.014 [75]       |
  0.017 [16]       |
  0.020 [0]        |
  0.023 [4]        |
  0.025 [0]        |
  0.028 [4]        |

Response time distribution:
  10.00% in 0.0001 secs
  25.00% in 0.0002 secs
  50.00% in 0.0002 secs
  75.00% in 0.0003 secs
  90.00% in 0.0004 secs
  95.00% in 0.0005 secs
  99.00% in 0.0008 secs
  99.90% in 0.0015 secs
  99.99% in 0.0030 secs


Details (average, fastest, slowest):
  DNS+dialup:   0.0012 secs, 0.0002 secs, 0.0026 secs
  DNS-lookup:   0.0001 secs, 0.0000 secs, 0.0023 secs

Status code distribution:
  [200] 12348259 responses

Error distribution:
  [13] aborted due to deadline

This is the next PR in the chain started at #1787

zoom: Option<u8>,
query: &'a str,
accept_enc: Option<AcceptEncoding>,
(accept_enc, if_none_match): (Option<AcceptEncoding>, Option<IfNoneMatch>),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is done like this to not make clippy angry that these are defintively too many arguments.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's just add the #[expect(...)] here - much better than to be confused about the meaning of the code


pub async fn get_http_response(&self, xyz: TileCoord) -> ActixResult<HttpResponse> {
let tile = self.get_tile_content(xyz).await?;
let hash = xxhash_rust::xxh3::xxh3_128(&tile.data);
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a future PR: plumb the hash from mbtiles and pg through the caching and merging in get_tile_content and below.

@CommanderStorm CommanderStorm marked this pull request as ready for review May 19, 2025 07:42
@CommanderStorm
Copy link
Member Author

So basically no performance impact. Brings up the point: Do we really want to use the hashes from the data?

@CommanderStorm CommanderStorm enabled auto-merge (squash) May 19, 2025 08:44
@nyurik
Copy link
Member

nyurik commented May 19, 2025

i would prefer to use the hash when its there. I was looking at the perf reports above, and it seems they are not aligned in the 2nd and 3rd row? Not sure which was which. The number of requests/sec is probably the most telling due to each request being served too fast.

@CommanderStorm
Copy link
Member Author

CommanderStorm commented May 19, 2025

Fixed the benchmarks.

The essence is that current version performs 5% worse in terms of Requests per second.
Change in response time is likely neglegable.

Regarding the using the hash when its there, that is something that I plan to do, just not in this PR. The reason is that that change snakes itsself through a lot of the codebase somehow.

Copy link
Member

@nyurik nyurik left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

well done, thx!!!

@CommanderStorm CommanderStorm merged commit 1b4a81e into maplibre:main May 20, 2025
20 checks passed
@CommanderStorm CommanderStorm deleted the basic-etag-handling branch May 21, 2025 00:22
@sharkAndshark
Copy link
Collaborator

thx!

@CommanderStorm CommanderStorm mentioned this pull request May 21, 2025
6 tasks
CommanderStorm added a commit that referenced this pull request May 27, 2025
This PR adds etag handling via an actix wrap instruction to all
"non-tile" endpoints.
I ommitted some endpoints which I suspect are not called more than once
such as `/` if the webui is not compiled in.

The reason for not being smarter for some is that honestly, the impact
of this is less than I expected based on benchmarks in #1834 and that
`actix-middleware-etag` uses the same hash algorithm.

<del>
I have not addded tests for this as frankly, this does not seem like a
feature that needs deep tests.
</del>
By request, this PR now includes all stemi-static headers.

---------

Co-authored-by: Yuri Astrakhan <yuriastrakhan@gmail.com>
Co-authored-by: sharkAndshark <zhangyijunmetro@hotmail.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants