xfmt

package module
v0.7.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 16, 2021 License: GPL-3.0 Imports: 10 Imported by: 0

README

Go xfmt package

Almost drop-in replacement of std fmt package but only for string args

Overview

This package is an almost drop-in replacement for std fmt package fns *print, *printf, and Errorf with advantages over the fmt package, however only exclusively for args of string type (or cast to this type). Advantages:

  • reflect package is excluded, so no heavy typecast and conversions with implicit checks
  • format string value is first parsed as tokens list' struct, suitable for caching
  • configurable caching of parsed format's tokens list' structs to avoid doing the same parsing job multiple times
  • special reusable buffer type with all needed fns for simple *print functions and *printf processing + with inplace subbuf for internal fmtXxx fns (mostly used by similar to strconv.Append*(buf []byte) fns, e.g. strconv.AppendQuote) drastically reduces heap reallocate-and-copy ops during write of results to buffer byteslice
  • unnecessary memory allocations have been significantly reduced - there are no unnecessary allocations at all
  • a lot of BCE optimizations performed (and many more needs to be done)
  • as a result, it is more faster and cheaper (approximately up to 2 times for both cpu and mem)

Status: RC1

  • Can be used in production that has its own internal tests
  • all the needed tests from the original fmt package have been adapted
    • for now it fails only one test case: wrong args count (too few) with implicit arg num in the mid of the format verbs' chain:
      adapted reorder test case 22 Sprintf("%s %[3]s %s", xfmt.SL{"1", "2"}) mismatch: want <1 %!s(BADINDEX) 2>, got <1 %!s(MISSING) %!s(MISSING)>
      some tests finished with errors: 1 of 28
      
  • finish up currently unfinished tests (format_test - testing for equality of the results with the fmt package' fns)
  • more tests are required (up to full code coverage with all of the edge and special cases)

API

It has the same subset of functions as the original fmt package, but with args of string type instead of interface{} type


// simple fns without format

func Fprint(w io.Writer, s ...string) (n int, err error)
func Print(s ...string) (n int, err error)
func Sprint(s ...string) string

// ln versions

func Fprintln(w io.Writer, s ...string) (n int, err error)
func Println(s ...string) (n int, err error)
func Sprintln(s ...string) string 

// format fns

func Fprintf(w io.Writer, format string, args ...string) (n int, err error)
func Printf(format string, args ...string) (n int, err error)
func Sprintf(format string, args ...string) string

// especial fns

func Errorf(format string, args ...string) error

// cache control

const (
	CacheAlways // always cache any fmt
	CacheRepetitions // cache only if format occurred more than once
	CacheDisabled // disables caching at all
)

// both thread-safe
func SetCacheThreshold(threshold uint)
func CacheThreshold() uint

Caching

By default, package cache tokens' list of any parsed format (CacheAlways), but this behavior is controlled by cacheThreshold internal value. Use SetCacheThreshold to set how many times format should be parsed (saw) by the parser before it will be cached. To check the threshold value, use CacheThreshold fn. Both fns are thread-safe (atomic r/w).

Mismatches with std fmt
  • simple no-ln fns Sprint, Fprint, and Print don't try to recognize args' initial types at all, so unlike such fmt fns they can't determine when to Spaces are added between operands when neither is a string and don't add spaces between args et all
  • some errors mark (especially for errors related to the tail of format) of formatting fns may differ from such
    returned by original fmt format fns
Limitations

Can't be used in Google App Engine' apps for now due to usage of unsafe package

Comparison benchmarks

go1.13> go test -bench=. -run "^$" -benchmem

goarch: amd64
pkg: github.com/Illirgway/go-xfmt

BenchmarkSprintfPadding/xfmt-6          73360842    16.1 ns/op    32 B/op    1 allocs/op
BenchmarkSprintfPadding/fmt-6           30769230    38.5 ns/op    48 B/op    2 allocs/op

BenchmarkSprintfEmpty/xfmt-6            445269012   2.69 ns/op     0 B/op    0 allocs/op
BenchmarkSprintfEmpty/fmt-6             164158686   7.75 ns/op     0 B/op    0 allocs/op

BenchmarkSprintfString/xfmt-6           98907889    12.8 ns/op     5 B/op    1 allocs/op
BenchmarkSprintfString/fmt-6            42857142    26.2 ns/op    21 B/op    2 allocs/op

BenchmarkSprintfTruncateString/xfmt-6   70339974    17.7 ns/op    16 B/op    1 allocs/op
BenchmarkSprintfTruncateString/fmt-6    26666666    42.3 ns/op    32 B/op    2 allocs/op

BenchmarkSprintfQuoteString/xfmt-6      9523808      127 ns/op    64 B/op    1 allocs/op
BenchmarkSprintfQuoteString/fmt-6       8450703      141 ns/op    80 B/op    2 allocs/op

BenchmarkSprintfPrefixedString/xfmt-6   62186904     19.4 ns/op   80 B/op    1 allocs/op
BenchmarkSprintfPrefixedString/fmt-6    29268291     40.4 ns/op   96 B/op    2 allocs/op

BenchmarkSprintfHexString/xfmt-6        49999999     24.7 ns/op    96 B/op   1 allocs/op
BenchmarkSprintfHexString/fmt-6         30000000     39.3 ns/op   112 B/op   2 allocs/op

BenchmarkManyArgs-6                     23529411     55.7 ns/op     0 B/op   0 allocs/op

fmt.Sprintf always has at least 1 + n memallocs, where n is a count of fn's args of non-interface type (and 1 is implicit bakary's copying during []byte buf -> string conversion)

Contributing

Plz don't send pull requests for now, only write issue tickets

LICENSE

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program. If not, see https://www.gnu.org/licenses/.

Copyright © 2021 Illirgway

Documentation

Index

Constants

View Source
const (
	CacheAlways      uint = 0
	CacheRepetitions      = 1        // cache only if format occurred more than once
	CacheDisabled         = ^uint(0) // max uint value
)
View Source
const (
	Space = ' '
	LF    = '\n'
)

Variables

This section is empty.

Functions

func CacheThreshold

func CacheThreshold() uint

thread-safe inlined

func Errorf

func Errorf(format string, args ...string) error

`go1.13: cannot inline Errorf: function too complex: cost 135 exceeds budget 80`

func Fprint

func Fprint(w io.Writer, s ...string) (n int, err error)

inlined

func Fprintf

func Fprintf(w io.Writer, format string, args ...string) (n int, err error)

`go1.13: cannot inline Fprintf: function too complex: cost 137 exceeds budget 80`

func Fprintln

func Fprintln(w io.Writer, s ...string) (n int, err error)

`Spaces are always added between operands and a newline is appended.` inlined

func Print

func Print(s ...string) (n int, err error)

`go1.13: cannot inline Print: function too complex: cost 87 exceeds budget 80`

func Printf

func Printf(format string, args ...string) (n int, err error)

`go1.13: cannot inline Printf: function too complex: cost 138 exceeds budget 80`

func Println

func Println(s ...string) (n int, err error)

`go1.13: cannot inline Println: function too complex: cost 87 exceeds budget 80`

func SetCacheThreshold

func SetCacheThreshold(threshold uint)

thread-safe inlined

func Sprint

func Sprint(s ...string) string

func Sprintf

func Sprintf(format string, args ...string) string

`go1.13: cannot inline Sprintf: function too complex: cost 127 exceeds budget 80`

func Sprintln

func Sprintln(s ...string) string

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL