Skip to content

Commit

Permalink
Merge pull request #14 from alipourhabibi/ref/faster-search
Browse files Browse the repository at this point in the history
Faster search with RWMutex
  • Loading branch information
Iajrdev authored Aug 28, 2024
2 parents 9aafac4 + f98fd15 commit dbedff3
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 31 deletions.
66 changes: 58 additions & 8 deletions api/v2/echo.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ type ListEntity struct {

type server struct {
list *linkedlist.LinkedList
mutex sync.Mutex
mutex sync.RWMutex
}

type customValidator struct {
Expand Down Expand Up @@ -79,6 +79,9 @@ func V2() (*echo.Echo, error) {
e.GET("/numbers/value/:value", s.Find)
e.GET("/numbers/index/:index", s.Get)

e.GET("/numbers/rwmutex/value/:value", s.RWMutexFind)
e.GET("/numbers/rwmutex/index/:index", s.RWMutexGet)

return e, nil
}

Expand All @@ -93,9 +96,9 @@ func (s *server) Insert(c echo.Context) error {
}

s.mutex.Lock()
defer s.mutex.Unlock()

ok := s.list.Insert(data.Index, data.Value)
s.mutex.Unlock()

if !ok {
return echo.NewHTTPError(echo.ErrBadRequest.Code, "Invalid index")
}
Expand All @@ -111,9 +114,9 @@ func (s *server) Remove(c echo.Context) error {
}

s.mutex.Lock()
defer s.mutex.Unlock()

ok := s.list.Remove(uint(index))
s.mutex.Unlock()

if !ok {
return echo.NewHTTPError(echo.ErrNotFound.Code, "Index not found")
}
Expand All @@ -131,9 +134,9 @@ func (s *server) Find(c echo.Context) error {
}

s.mutex.Lock()
defer s.mutex.Unlock()

index, ok := s.list.Find(value)
s.mutex.Unlock()

if !ok {
return echo.NewHTTPError(echo.ErrNotFound.Code, "Value not found")
}
Expand All @@ -154,9 +157,56 @@ func (s *server) Get(c echo.Context) error {
}

s.mutex.Lock()
defer s.mutex.Unlock()
value, ok := s.list.Get(uint(index))
s.mutex.Unlock()

if !ok {
return echo.NewHTTPError(echo.ErrNotFound.Code, "Index not found")
}
data := ListEntity{
Index: uint(index),
Value: value,
}

c.JSON(http.StatusOK, data)
return nil
}

func (s *server) RWMutexFind(c echo.Context) error {
valueStr := c.Param("value")
value, err := strconv.Atoi(valueStr)
if err != nil {
fmt.Println(err)
return echo.NewHTTPError(echo.ErrBadRequest.Code, "Invalid value")
}

s.mutex.RLock()
index, ok := s.list.Find(value)
s.mutex.RUnlock()

if !ok {
return echo.NewHTTPError(echo.ErrNotFound.Code, "Value not found")
}

data := ListEntity{
Index: index,
Value: value,
}
c.JSON(http.StatusOK, data)
return nil
}

func (s *server) RWMutexGet(c echo.Context) error {
indexStr := c.Param("index")
index, err := strconv.ParseUint(indexStr, 10, 32)
if err != nil {
return echo.NewHTTPError(echo.ErrBadRequest.Code, "Invalid index")
}

s.mutex.RLock()
value, ok := s.list.Get(uint(index))
s.mutex.RUnlock()

if !ok {
return echo.NewHTTPError(echo.ErrNotFound.Code, "Index not found")
}
Expand Down
59 changes: 49 additions & 10 deletions benchmark.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ cleanup() {
[ -e "$FIND_FILE" ] && unlink "$FIND_FILE"
[ -e "post.lua" ] && unlink "post.lua"
[ -e "get.lua" ] && unlink "get.lua"
[ -e "rwget.lua" ] && unlink "rwget.lua"
echo "Cleanup completed"
}

Expand Down Expand Up @@ -54,13 +55,6 @@ request = function()
end
EOF

# Benchmark the insert operation
echo "Benchmarking insert operation..."
if ! wrk -t12 -c100 -d30s -s post.lua http://localhost:8080; then
echo "Error fibding on line $line"
exit 1
fi

# Create a script for wrk to use for GET requests
cat <<EOF > get.lua
wrk.method = "GET"
Expand All @@ -77,10 +71,55 @@ request = function()
end
EOF

# Create a script for wrk to use for GET requests for RWMutex
cat <<EOF > rwget.lua
wrk.method = "GET"
values = {}
index = 1
$(awk '{print "table.insert(values, \"" $0 "\")"}' $FIND_FILE)
request = function()
local path = "/v2/numbers/rwmutex/value/" .. values[index]
index = index + 1
if index > #values then
index = 1
end
return wrk.format(nil, path)
end
EOF

# Benchmark the insert operation
echo "Benchmarking insert operation..."
wrk -t12 -c100 -d30s -s post.lua http://localhost:8080 &
pid1=$!

# Benchmark the find operation
echo "Benchmarking find operation..."
if ! wrk -t12 -c100 -d30s -s get.lua http://localhost:8080; then
exit 1
wrk -t12 -c100 -d30s -s get.lua http://localhost:8080 &
pid2=$!

# Benchmark the RWMutex find operation
echo "Benchmarking RWMutex find operation..."
wrk -t12 -c100 -d30s -s rwget.lua http://localhost:8080 &
pid3=$!

# Wait for all background processes to finish
wait $pid1 $pid2 $pid3

# Check the exit statuses and exit with an error if any command failed
if [ $status1 -ne 0 ]; then
echo "Error: Benchmarking insert operation failed"
exit 1
fi

echo "completed successfully"
if [ $status2 -ne 0 ]; then
echo "Error: Benchmarking find operation failed"
exit 1
fi

if [ $status3 -ne 0 ]; then
echo "Error: Benchmarking RWMutex find operation failed"
exit 1
fi

echo "Completed successfully"

63 changes: 50 additions & 13 deletions grafana/provisioning/dashboards/my_dashboard.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,41 +12,77 @@
"title": "HTTP Requests",
"datasource": "Prometheus",
"targets": [

{
"expr": "histogram_quantile(0.50, sum(rate(myapp_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "p50",
"refId": "A",
"expr": "histogram_quantile(0.50, sum(rate(myapp_request_duration_seconds_bucket{method=\"POST\", url=\"/numbers/:index/:value\"}[5m])) by (le))",
"legendFormat": "p50 - POST /numbers/:index/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.90, sum(rate(myapp_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "p90",
"refId": "B",
"expr": "histogram_quantile(0.50, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/value/:value\"}[5m])) by (le))",
"legendFormat": "p50 - GET /numbers/value/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.99, sum(rate(myapp_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "p99",
"refId": "C",
"expr": "histogram_quantile(0.50, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/rwmutex/value/:value\"}[5m])) by (le))",
"legendFormat": "p50 - GET /numbers/rwmutex/value/:value",
"editorMode": "code",
"range": true
},

{
"expr": "histogram_quantile(0.90, sum(rate(myapp_request_duration_seconds_bucket{method=\"POST\", url=\"/numbers/:index/:value\"}[5m])) by (le))",
"legendFormat": "p90 - POST /numbers/:index/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.90, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/value/:value\"}[5m])) by (le))",
"legendFormat": "p90 - GET /numbers/value/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.90, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/rwmutex/value/:value\"}[5m])) by (le))",
"legendFormat": "p90 - GET /numbers/rwmutex/value/:value",
"editorMode": "code",
"range": true
},

{
"expr": "histogram_quantile(0.95, sum(rate(myapp_request_duration_seconds_bucket{method=\"POST\", url=\"/numbers/:index/:value\"}[5m])) by (le))",
"legendFormat": "p95 - POST /numbers/:index/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.95, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/value/:value\"}[5m])) by (le))",
"legendFormat": "p95 - GET /numbers/value/:value",
"editorMode": "code",
"range": true
},
{
"expr": "histogram_quantile(0.95, sum(rate(myapp_request_duration_seconds_bucket{method=\"GET\", url=\"/numbers/rwmutex/value/:value\"}[5m])) by (le))",
"legendFormat": "p95 - GET /numbers/rwmutex/value/:value",
"editorMode": "code",
"range": true
},

{
"expr": "sum(rate(myapp_request_duration_seconds_count[5m]))",
"legendFormat": "Total Requests",
"refId": "D",
"editorMode": "builder",
"range": true
},
{
"expr": "sum(myapp_request_duration_seconds_sum)",
"legendFormat": "Sum Duration",
"refId": "E",
"editorMode": "builder",
"range": true
}

],
"fieldConfig": {
"defaults": {
Expand All @@ -67,7 +103,7 @@
}
]
},
"unit": "short"
"unit": "ms"
},
"overrides": []
},
Expand All @@ -89,7 +125,7 @@
},
"yaxes": [
{
"format": "short",
"format": "ms",
"show": true
},
{
Expand All @@ -100,3 +136,4 @@
}
]
}

29 changes: 29 additions & 0 deletions hurl-tests/tests.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,55 @@ HTTP 200
jsonpath "$.index" == 0
jsonpath "$.value" == 2

GET http://{{host}}/v2/numbers/rwmutex/index/0
HTTP 200
[Asserts]
jsonpath "$.index" == 0
jsonpath "$.value" == 2

GET http://{{host}}/v2/numbers/index/2
HTTP 404
[Asserts]
jsonpath "$.message" == "Index not found"

GET http://{{host}}/v2/numbers/rwmutex/index/2
HTTP 404
[Asserts]
jsonpath "$.message" == "Index not found"

GET http://{{host}}/v2/numbers/value/4
HTTP 200
[Asserts]
jsonpath "$.index" == 1
jsonpath "$.value" == 4

GET http://{{host}}/v2/numbers/rwmutex/value/4
HTTP 200
[Asserts]
jsonpath "$.index" == 1
jsonpath "$.value" == 4


GET http://{{host}}/v2/numbers/value/6
HTTP 404
[Asserts]
jsonpath "$.message" == "Value not found"

GET http://{{host}}/v2/numbers/rwmutex/value/6
HTTP 404
[Asserts]
jsonpath "$.message" == "Value not found"


DELETE http://{{host}}/v2/numbers/1
HTTP 200

GET http://{{host}}/v2/numbers/index/1
HTTP 404
[Asserts]
jsonpath "$.message" == "Index not found"

GET http://{{host}}/v2/numbers/rwmutex/index/1
HTTP 404
[Asserts]
jsonpath "$.message" == "Index not found"

0 comments on commit dbedff3

Please sign in to comment.