Skip to content

Prevent Unnecessary Computation in Broadcaster (internal/broadcast/dispatcher.go) #126

Closed

Description

@messede-degod
  • JSONLite, JSON, JSONDomains are computed for each entry without checking if current clients need them
  • most installations of certstream server-go would use a single client with a single subscription type (same client cannot have multiple subscription types as per config)
  • I believe there would be non trivial amount of savings in CPU if we switch to computing bytes only for the subscription types that are actually needed

func (bm *Dispatcher) broadcaster() {
for {
var data []byte
// Take entry out of broadcast channel and generate JSON representations for the entry.
entry := <-bm.MessageQueue
dataLite := entry.JSONLite()
dataFull := entry.JSON()
dataDomain := entry.JSONDomains()
bm.clientLock.RLock()
for _, c := range bm.clients {
switch c.SubType() {
case SubTypeLite:
data = dataLite
case SubTypeFull:
data = dataFull
case SubTypeDomain:
data = dataDomain
default:
// This should never happen, but if it does, we log it and skip the client.
log.Printf("Unknown subscription type '%d' for client '%s'. Skipping this client!\n", c.SubType(), c.Name())
continue
}
c.Write(data)
}
bm.clientLock.RUnlock()
}
}

A updated version of this code would look like:

// broadcaster is run in a goroutine and handles the dispatching of certs to clients.
func (bm *Dispatcher) broadcaster() {
	for {
		// Take entry out of broadcast channel and generate JSON representations for the entry.
		entry := <-bm.MessageQueue
		computeBytes := entryByteComputer(&entry)

		bm.clientLock.RLock()

		for _, c := range bm.clients {
			data, err := computeBytes(c.SubType())
			// This should never happen, but if it does, we log it and skip the client.
			if err != nil {
				log.Printf("%s on client '%s'. Skipping this client!\n", err.Error(), c.Name())
				continue
			}

			c.Write(data)
		}

		bm.clientLock.RUnlock()
	}
}

// Compute and cache bytes as per necessity
func entryByteComputer(entry *models.Entry) func(subType SubscriptionType) ([]byte, error) {
	dataLite := []byte{}
	isDataLiteComputed := false

	dataFull := []byte{}
	isDataFullComputed := false

	dataDomain := []byte{}
	isDataDomainComputed := false

	return func(subType SubscriptionType) ([]byte, error) {
		switch subType {
		case SubTypeLite:
			if !isDataLiteComputed {
				dataLite = entry.JSONLite()
				isDataLiteComputed = true
			}
			return dataLite, nil

		case SubTypeFull:
			if !isDataFullComputed {
				dataFull = entry.JSON()
				isDataFullComputed = true
			}
			return dataFull, nil

		case SubTypeDomain:
			if !isDataDomainComputed {
				dataDomain = entry.JSONDomains()
				isDataDomainComputed = true
			}
			return dataDomain, nil

		default:
			return []byte{}, fmt.Errorf("Unknown subscription type '%d'", subType)
		}
	}
}

Activity

  1. messede-degod commented on Sep 23, 2026

    @messede-degod
    ContributorAuthor

    PR made here: #128

  2. d-Rickyy-b commented on Sep 25, 2026

    @d-Rickyy-b
    Owner

    Thanks for the reasonable suggestion. It's definitely smart to not calculate the JSON when there is no client connected at all or when the connected client does not need any of the other two types.

    I think your current suggestion on how to implement this is not quite the way I would have implemented it. I will discuss the details via comments to your PR later.

  3. added a commit that references this issue on Sep 27, 2026
    eee5bf5
  4. messede-degod commented on Sep 27, 2026

    @messede-degod
    ContributorAuthor

    Fixed by: #128

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions