Skip to content

Conversation

1911860538
Copy link
Contributor

Improves the ContentSubtype function by adding special handling for the "application/json" content type,
reducing processing time.
Additionally, replaces strings.Index with strings.IndexByte for more efficient character search.
Enhance performance in high-frequency HTTP request and response processing.

Below is my local test code.
content_type_test.go

package httputil

import (
	"strings"
	"testing"
)

func ContentSubtypeOriginal(contentType string) string {
	left := strings.Index(contentType, "/")
	if left == -1 {
		return ""
	}
	right := strings.Index(contentType, ";")
	if right == -1 {
		right = len(contentType)
	}
	if right < left {
		return ""
	}
	return contentType[left+1 : right]
}

func ContentSubtypeOptimized(contentType string) string {
	switch contentType {
	case "":
		return ""
	case "application/json":
		return "json"
	}

	left := strings.IndexByte(contentType, '/')
	if left == -1 {
		return ""
	}
	right := strings.IndexByte(contentType, ';')
	if right == -1 {
		right = len(contentType)
	}
	if right < left {
		return ""
	}
	return contentType[left+1 : right]
}

var result string

func BenchmarkContentSubtype_json(b *testing.B) {
	var r string
	contentType := "application/json"

	b.Run("original", func(b *testing.B) {
		b.ResetTimer()
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			r = ContentSubtypeOriginal(contentType)
		}
		result = r
	})

	b.Run("optimized", func(b *testing.B) {
		b.ResetTimer()
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			r = ContentSubtypeOptimized(contentType)
		}
		result = r
	})
}

func BenchmarkContentSubtype_html(b *testing.B) {
	var r string
	contentType := "text/html; charset=utf-8"

	b.Run("original", func(b *testing.B) {
		b.ResetTimer()
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			r = ContentSubtypeOriginal(contentType)
		}
		result = r
	})

	b.Run("optimized", func(b *testing.B) {
		b.ResetTimer()
		b.ReportAllocs()
		for i := 0; i < b.N; i++ {
			r = ContentSubtypeOptimized(contentType)
		}
		result = r
	})
}

benchmark output

goos: darwin
goarch: amd64
pkg: testgolang/kratos/httputil
cpu: Intel(R) Core(TM) i7-8569U CPU @ 2.80GHz
BenchmarkContentSubtype_json
BenchmarkContentSubtype_json/original
BenchmarkContentSubtype_json/original-8         	99002124	        11.26 ns/op	       0 B/op	       0 allocs/op
BenchmarkContentSubtype_json/optimized
BenchmarkContentSubtype_json/optimized-8        	463418761	         2.528 ns/op	       0 B/op	       0 allocs/op
BenchmarkContentSubtype_html
BenchmarkContentSubtype_html/original
BenchmarkContentSubtype_html/original-8         	92809951	        12.77 ns/op	       0 B/op	       0 allocs/op
BenchmarkContentSubtype_html/optimized
BenchmarkContentSubtype_html/optimized-8        	129674308	         9.145 ns/op	       0 B/op	       0 allocs/op
PASS

Process finished with the exit code 0

@dosubot dosubot bot added the size:S This PR changes 10-29 lines, ignoring generated files. label May 6, 2025
@1911860538 1911860538 closed this May 6, 2025
@1911860538 1911860538 reopened this May 6, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
size:S This PR changes 10-29 lines, ignoring generated files.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant