Оптимизируй производительность кода

Без изменения Logger можно сериализовать Log и Close обёрткой с mutex. Это обеспечивает согласованность, но не ускоряет сам диск и не создаёт определённый порядок одновременных вызовов заранее.

Короткий ответ

Что ответить на собеседовании

Без изменения Logger можно сериализовать Log и Close обёрткой с mutex. Это обеспечивает согласованность, но не ускоряет сам диск и не создаёт определённый порядок одновременных вызовов заранее.

Подробный разбор

Ответ с пояснениями

Условие

Требуется устранить узкие места, влияющие на скорость работы программы, при этом менять внутреннюю реализацию логгера нельзя.

type Logger interface {
  Log(message string) error
  Close() error
}

type FileLogger struct{ file *os.File }

func NewFileLogger(path string) (*FileLogger, error) {
  fileHandle, err := os.Create(path)
  if err != nil {
    return nil, err
  }
  return &FileLogger{fileHandle}, nil
}

func (fl FileLogger) Log(message string) error {
  _, err := fl.file.WriteString(message + "\n")
  return err
}

func (fl FileLogger) Close() error {
  return fl.file.Close()
}

// ...

type SequentialLogger struct {
  inner Logger
}

func NewSequentialLogger(inner Logger) *SequentialLogger {
  return &SequentialLogger{inner}
}

func (sl *SequentialLogger) Log(message string) error {
  // TODO: добавить реализацию, сохраняющую порядок записи и не ухудшающую производительность
}

Ответ

Без изменения Logger можно сериализовать Log и Close обёрткой с mutex. Это обеспечивает согласованность, но не ускоряет сам диск и не создаёт определённый порядок одновременных вызовов заранее.

Импорты sync и errors; существующий конструктор замените на keyed literal &SequentialLogger{inner: inner}:

type SequentialLogger struct {
    inner Logger
    mu sync.Mutex
    closed bool
}
func (sl *SequentialLogger) Log(message string) error {
    sl.mu.Lock()
    defer sl.mu.Unlock()
    if sl.closed { return errors.New("logger closed") }
    return sl.inner.Log(message)
}
func (sl *SequentialLogger) Close() error {
    sl.mu.Lock()
    defer sl.mu.Unlock()
    if sl.closed { return nil }
    sl.closed = true
    return sl.inner.Close()
}

Порядок — порядок захвата lock; строгая внешняя последовательность требует номеров сообщений. Асинхронная очередь снижает задержку вызывающего, но меняет смысл возврата error и требует flush/backpressure. Без изменения гарантий нельзя обещать бесплатное ускорение.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее