Commit Graph

29 Commits

Author SHA1 Message Date
Colin a4f41768ba
Optimize WebSocket implementation for millions of connections
- Implement sharded client storage (256 shards by default) to eliminate mutex contention
- Replace slice-based storage with map structure for O(1) token lookup
- Increase WebSocket buffer sizes (8192 bytes) and channel buffers (10 messages)
- Optimize Notify method with per-shard locking
- Add configuration options for shard count and buffer sizes
- Add comprehensive benchmarking setup with docker-compose
- Include k6 load testing scripts for WebSocket performance testing
- All existing tests pass with new sharded implementation
2025-11-20 14:43:33 -05:00
昨夜雨疏风骤 4bc42d2c1d
Optimize uniq function for better performance (#852)
Improve the performance of the unique function by:
1. Pre-allocating map capacity with len(s) to avoid frequent map resizing
2. Pre-allocating result slice capacity with len(s) to reduce append overhead
3. Reducing the number of traversals performs well under the condition of a large number of elements

These changes maintain the original behavior (preserving element order) 
while reducing memory allocation operations, especially effective for 
large slices (100k+ elements) with benchmark showing ~25% speedup.

No breaking changes, the function signature and output order remain unchanged.
2025-10-03 01:17:47 +00:00
Eng Zer Jun 0bfa5ca4d9
perf: avoid allocations with `(*regexp.Regexp).MatchString` (#604)
We should use `(*regexp.Regexp).MatchString` instead of
`(*regexp.Regexp).Match([]byte(...))` when matching string to avoid
unnecessary `[]byte` conversions and reduce allocations.

Example benchmark:

var allowedOrigin = regexp.MustCompile(".*.example.com")

func BenchmarkMatch(b *testing.B) {
	for i := 0; i < b.N; i++ {
		if match := allowedOrigin.Match([]byte("www.example.com")); !match {
			b.Fail()
		}
	}
}

func BenchmarkMatchString(b *testing.B) {
	for i := 0; i < b.N; i++ {
		if match := allowedOrigin.MatchString("wwww.example.com"); !match {
			b.Fail()
		}
	}
}

goos: linux
goarch: amd64
pkg: github.com/gotify/server/v2/api/stream
cpu: AMD Ryzen 7 PRO 4750U with Radeon Graphics
BenchmarkMatch-16          	 2076819	       647.7 ns/op	      16 B/op	       1 allocs/op
BenchmarkMatchString-16    	 2536326	       442.0 ns/op	       0 B/op	       0 allocs/op
PASS
ok  	github.com/gotify/server/v2/api/stream	3.552s

Signed-off-by: Eng Zer Jun <engzerjun@gmail.com>
2023-10-23 15:57:15 +00:00
Jannis Mattheis 9592cc95c9 fix: update go-swagger 2023-09-16 21:06:54 +02:00
Jannis Mattheis a3ce298729 Fix stream_test flakiness 2023-08-06 12:30:22 +02:00
eternal-flame-AD 7bf80ee6f1 Add last used to client & application 2023-08-06 12:30:22 +02:00
mateuscelio 0fb584d7f7 Update docs 2022-12-03 10:45:07 +01:00
Jannis Mattheis 3454dcd602 Use golangci-lint 2020-11-01 10:47:02 +01:00
Jannis Mattheis 909eeff406 Make keepalive period configurable 2020-09-10 16:22:04 +00:00
Jannis Mattheis 7b90b8a8f5 Use v2 in package path 2020-05-08 10:43:17 +02:00
Jannis Mattheis 0a7a5cd619 Add logging to websocket errors 2019-11-28 21:39:47 +01:00
饺子w 178c76f410 Fix websocket allowed origin (#150) 2019-03-14 18:16:24 +01:00
Jannis Mattheis 5c5965f2fd Log web socket errors 2019-03-07 18:29:46 +01:00
eternal-flame-AD e5b24f4c92 Add plugin feature
Fixed database migration
Added a plugin system based on the go plugin package
2019-02-09 12:52:01 +01:00
eternal-flame-AD de09aae987 add extras to message model 2019-02-02 13:06:30 +01:00
Jannis Mattheis 68b160997d Format all go files 2019-01-01 23:34:42 +01:00
Eugene Gavrilov b5b2f19dc2 [#23] Fix check same origin function 2018-12-12 21:30:59 +01:00
Jannis Mattheis 76ca344b77 Make security more compact 2018-11-24 11:31:32 +01:00
Jannis Mattheis 9e7859c36c Add missing bad request / not found definitions 2018-11-24 11:31:32 +01:00
Jannis Mattheis dfb71dabbc Make produce/consumes more compact 2018-11-24 11:31:32 +01:00
Jannis Mattheis c841e1cd24 Move swagger comments to api 2018-11-24 11:31:32 +01:00
Jannis Mattheis ee723918f9 Add once test 2018-11-22 20:59:29 +01:00
Jannis Mattheis 79e1dc9c9a Prevent deadlock on stream.Close()
GR = goroutine
[GR#1] http server gets closed
[GR#2] client.NotifyClose() will be executed
[GR#2] client.once.Do will be executed (lock's client.once.m)
[GR#1] stream.Close will be executed (lock's stream.lock)
[GR#1] client.Close will be executed (waits for client.once.m)
[GR#2] stream.remove will be executed (waits for stream.lock)

GR#1 holds lock stream.lock and waits for client.once.m
GR#2 holds lock client.once.m and waits for stream.lock

We prevent the deadlock with releasing the client.once.m lock earlier.
2018-11-22 20:59:29 +01:00
Jannis Mattheis a992bc1506 Prevent possible race condition on SetPingHandler
conn.ReadMessage and conn.SetPingHandler are executed
in different goroutines.
2018-11-22 20:59:29 +01:00
Jannis Mattheis 80eec6ae3a Remove monkey dependency 2018-11-06 21:38:15 +01:00
Jannis Mattheis 1262f43846 Close web socket connection on delete user 2018-04-02 12:35:16 +02:00
Jannis Mattheis 6954fb5adf Close web socket connection on delete client 2018-04-02 12:35:16 +02:00
Jannis Mattheis 0f2e7cf5e2 Use gofmt -s 2018-03-25 19:33:29 +02:00
Jannis Mattheis 01c6800ae8 Move stream to api 2018-03-25 19:33:29 +02:00