From 50c5996280f4fff4acab0f9b6702928bc993042d Mon Sep 17 00:00:00 2001 From: jvoisin Date: Fri, 8 Aug 2025 22:55:35 +0200 Subject: [PATCH] refactor: remove some `fmt.Sprintf` calls fmt.Sprintf is slow, so let's get rid of it in trivial cases that are in (at least) moderately hot paths. --- internal/model/icon.go | 3 +- internal/storage/batch.go | 9 +++--- internal/storage/entry_pagination_builder.go | 9 +++--- internal/storage/entry_query_builder.go | 29 ++++++++++---------- internal/storage/feed_query_builder.go | 8 +++--- 5 files changed, 30 insertions(+), 28 deletions(-) diff --git a/internal/model/icon.go b/internal/model/icon.go index 239e7001..45b76fb4 100644 --- a/internal/model/icon.go +++ b/internal/model/icon.go @@ -5,7 +5,6 @@ package model // import "miniflux.app/v2/internal/model" import ( "encoding/base64" - "fmt" ) // Icon represents a website icon (favicon) @@ -19,7 +18,7 @@ type Icon struct { // DataURL returns the data URL of the icon. func (i *Icon) DataURL() string { - return fmt.Sprintf("%s;base64,%s", i.MimeType, base64.StdEncoding.EncodeToString(i.Content)) + return i.MimeType + ";base64," + base64.StdEncoding.EncodeToString(i.Content) } // Icons represents a list of icons. diff --git a/internal/storage/batch.go b/internal/storage/batch.go index a7939ee1..3cd58d53 100644 --- a/internal/storage/batch.go +++ b/internal/storage/batch.go @@ -7,6 +7,7 @@ import ( "database/sql" "fmt" "log/slog" + "strconv" "strings" "miniflux.app/v2/internal/model" @@ -33,20 +34,20 @@ func (b *BatchBuilder) WithBatchSize(batchSize int) *BatchBuilder { } func (b *BatchBuilder) WithUserID(userID int64) *BatchBuilder { - b.conditions = append(b.conditions, fmt.Sprintf("user_id = $%d", len(b.args)+1)) + b.conditions = append(b.conditions, "user_id = $"+strconv.Itoa(len(b.args)+1)) b.args = append(b.args, userID) return b } func (b *BatchBuilder) WithCategoryID(categoryID int64) *BatchBuilder { - b.conditions = append(b.conditions, fmt.Sprintf("category_id = $%d", len(b.args)+1)) + b.conditions = append(b.conditions, "category_id = $"+strconv.Itoa(len(b.args)+1)) b.args = append(b.args, categoryID) return b } func (b *BatchBuilder) WithErrorLimit(limit int) *BatchBuilder { if limit > 0 { - b.conditions = append(b.conditions, fmt.Sprintf("parsing_error_count < $%d", len(b.args)+1)) + b.conditions = append(b.conditions, "parsing_error_count < $"+strconv.Itoa(len(b.args)+1)) b.args = append(b.args, limit) } return b @@ -81,7 +82,7 @@ func (b *BatchBuilder) FetchJobs() (model.JobList, error) { query += " ORDER BY next_check_at ASC" if b.batchSize > 0 { - query += fmt.Sprintf(" LIMIT %d", b.batchSize) + query += " LIMIT " + strconv.Itoa(b.batchSize) } rows, err := b.db.Query(query, b.args...) diff --git a/internal/storage/entry_pagination_builder.go b/internal/storage/entry_pagination_builder.go index cc56c6b2..0e1251ce 100644 --- a/internal/storage/entry_pagination_builder.go +++ b/internal/storage/entry_pagination_builder.go @@ -6,6 +6,7 @@ package storage // import "miniflux.app/v2/internal/storage" import ( "database/sql" "fmt" + "strconv" "strings" "miniflux.app/v2/internal/model" @@ -37,7 +38,7 @@ func (e *EntryPaginationBuilder) WithStarred() { // WithFeedID adds feed_id to the condition. func (e *EntryPaginationBuilder) WithFeedID(feedID int64) { if feedID != 0 { - e.conditions = append(e.conditions, fmt.Sprintf("e.feed_id = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.feed_id = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, feedID) } } @@ -45,7 +46,7 @@ func (e *EntryPaginationBuilder) WithFeedID(feedID int64) { // WithCategoryID adds category_id to the condition. func (e *EntryPaginationBuilder) WithCategoryID(categoryID int64) { if categoryID != 0 { - e.conditions = append(e.conditions, fmt.Sprintf("f.category_id = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "f.category_id = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, categoryID) } } @@ -53,7 +54,7 @@ func (e *EntryPaginationBuilder) WithCategoryID(categoryID int64) { // WithStatus adds status to the condition. func (e *EntryPaginationBuilder) WithStatus(status string) { if status != "" { - e.conditions = append(e.conditions, fmt.Sprintf("e.status = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.status = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, status) } } @@ -124,7 +125,7 @@ func (e *EntryPaginationBuilder) getPrevNextID(tx *sql.Tx) (prevID int64, nextID ` subCondition := strings.Join(e.conditions, " AND ") - finalCondition := fmt.Sprintf("ep.id = $%d", len(e.args)+1) + finalCondition := "ep.id = $" + strconv.Itoa(len(e.args)+1) query := fmt.Sprintf(cte, e.order, subCondition, finalCondition) e.args = append(e.args, e.entryID) diff --git a/internal/storage/entry_query_builder.go b/internal/storage/entry_query_builder.go index 9e411c92..a3671d03 100644 --- a/internal/storage/entry_query_builder.go +++ b/internal/storage/entry_query_builder.go @@ -6,6 +6,7 @@ package storage // import "miniflux.app/v2/internal/storage" import ( "database/sql" "fmt" + "strconv" "strings" "time" @@ -60,28 +61,28 @@ func (e *EntryQueryBuilder) WithStarred(starred bool) *EntryQueryBuilder { // BeforeChangedDate adds a condition < changed_at func (e *EntryQueryBuilder) BeforeChangedDate(date time.Time) *EntryQueryBuilder { - e.conditions = append(e.conditions, fmt.Sprintf("e.changed_at < $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.changed_at < $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, date) return e } // AfterChangedDate adds a condition > changed_at func (e *EntryQueryBuilder) AfterChangedDate(date time.Time) *EntryQueryBuilder { - e.conditions = append(e.conditions, fmt.Sprintf("e.changed_at > $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.changed_at > $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, date) return e } // BeforePublishedDate adds a condition < published_at func (e *EntryQueryBuilder) BeforePublishedDate(date time.Time) *EntryQueryBuilder { - e.conditions = append(e.conditions, fmt.Sprintf("e.published_at < $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.published_at < $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, date) return e } // AfterPublishedDate adds a condition > published_at func (e *EntryQueryBuilder) AfterPublishedDate(date time.Time) *EntryQueryBuilder { - e.conditions = append(e.conditions, fmt.Sprintf("e.published_at > $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.published_at > $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, date) return e } @@ -89,7 +90,7 @@ func (e *EntryQueryBuilder) AfterPublishedDate(date time.Time) *EntryQueryBuilde // BeforeEntryID adds a condition < entryID. func (e *EntryQueryBuilder) BeforeEntryID(entryID int64) *EntryQueryBuilder { if entryID != 0 { - e.conditions = append(e.conditions, fmt.Sprintf("e.id < $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.id < $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, entryID) } return e @@ -98,7 +99,7 @@ func (e *EntryQueryBuilder) BeforeEntryID(entryID int64) *EntryQueryBuilder { // AfterEntryID adds a condition > entryID. func (e *EntryQueryBuilder) AfterEntryID(entryID int64) *EntryQueryBuilder { if entryID != 0 { - e.conditions = append(e.conditions, fmt.Sprintf("e.id > $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.id > $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, entryID) } return e @@ -114,7 +115,7 @@ func (e *EntryQueryBuilder) WithEntryIDs(entryIDs []int64) *EntryQueryBuilder { // WithEntryID filter by entry ID. func (e *EntryQueryBuilder) WithEntryID(entryID int64) *EntryQueryBuilder { if entryID != 0 { - e.conditions = append(e.conditions, fmt.Sprintf("e.id = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.id = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, entryID) } return e @@ -123,7 +124,7 @@ func (e *EntryQueryBuilder) WithEntryID(entryID int64) *EntryQueryBuilder { // WithFeedID filter by feed ID. func (e *EntryQueryBuilder) WithFeedID(feedID int64) *EntryQueryBuilder { if feedID > 0 { - e.conditions = append(e.conditions, fmt.Sprintf("e.feed_id = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.feed_id = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, feedID) } return e @@ -132,7 +133,7 @@ func (e *EntryQueryBuilder) WithFeedID(feedID int64) *EntryQueryBuilder { // WithCategoryID filter by category ID. func (e *EntryQueryBuilder) WithCategoryID(categoryID int64) *EntryQueryBuilder { if categoryID > 0 { - e.conditions = append(e.conditions, fmt.Sprintf("f.category_id = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "f.category_id = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, categoryID) } return e @@ -141,7 +142,7 @@ func (e *EntryQueryBuilder) WithCategoryID(categoryID int64) *EntryQueryBuilder // WithStatus filter by entry status. func (e *EntryQueryBuilder) WithStatus(status string) *EntryQueryBuilder { if status != "" { - e.conditions = append(e.conditions, fmt.Sprintf("e.status = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.status = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, status) } return e @@ -170,7 +171,7 @@ func (e *EntryQueryBuilder) WithTags(tags []string) *EntryQueryBuilder { // WithoutStatus set the entry status that should not be returned. func (e *EntryQueryBuilder) WithoutStatus(status string) *EntryQueryBuilder { if status != "" { - e.conditions = append(e.conditions, fmt.Sprintf("e.status <> $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.status <> $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, status) } return e @@ -178,7 +179,7 @@ func (e *EntryQueryBuilder) WithoutStatus(status string) *EntryQueryBuilder { // WithShareCode set the entry share code. func (e *EntryQueryBuilder) WithShareCode(shareCode string) *EntryQueryBuilder { - e.conditions = append(e.conditions, fmt.Sprintf("e.share_code = $%d", len(e.args)+1)) + e.conditions = append(e.conditions, "e.share_code = $"+strconv.Itoa(len(e.args)+1)) e.args = append(e.args, shareCode) return e } @@ -454,11 +455,11 @@ func (e *EntryQueryBuilder) buildSorting() string { } if e.limit > 0 { - parts += fmt.Sprintf(" LIMIT %d", e.limit) + parts += " LIMIT " + strconv.Itoa(e.limit) } if e.offset > 0 { - parts += fmt.Sprintf(" OFFSET %d", e.offset) + parts += " OFFSET " + strconv.Itoa(e.offset) } return parts diff --git a/internal/storage/feed_query_builder.go b/internal/storage/feed_query_builder.go index c30ccd7c..846907f7 100644 --- a/internal/storage/feed_query_builder.go +++ b/internal/storage/feed_query_builder.go @@ -67,7 +67,7 @@ func (f *FeedQueryBuilder) WithCounters() *FeedQueryBuilder { // WithSorting add a sort expression. func (f *FeedQueryBuilder) WithSorting(column, direction string) *FeedQueryBuilder { - f.sortExpressions = append(f.sortExpressions, fmt.Sprintf("%s %s", column, direction)) + f.sortExpressions = append(f.sortExpressions, column+" "+direction) return f } @@ -95,7 +95,7 @@ func (f *FeedQueryBuilder) buildSorting() string { var parts string if len(f.sortExpressions) > 0 { - parts += fmt.Sprintf(" ORDER BY %s", strings.Join(f.sortExpressions, ", ")) + parts += " ORDER BY " + strings.Join(f.sortExpressions, ", ") } if len(parts) > 0 { @@ -103,11 +103,11 @@ func (f *FeedQueryBuilder) buildSorting() string { } if f.limit > 0 { - parts += fmt.Sprintf(" LIMIT %d", f.limit) + parts += " LIMIT " + strconv.Itoa(f.limit) } if f.offset > 0 { - parts += fmt.Sprintf(" OFFSET %d", f.offset) + parts += " OFFSET " + strconv.Itoa(f.offset) } return parts