diff options
Diffstat (limited to 'internal')
| -rw-r--r-- | internal/media/metadata.go | 2 | ||||
| -rw-r--r-- | internal/media/probe.go | 5 | ||||
| -rw-r--r-- | internal/media/util.go | 25 |
3 files changed, 25 insertions, 7 deletions
diff --git a/internal/media/metadata.go b/internal/media/metadata.go index c1fa58645..6524784fd 100644 --- a/internal/media/metadata.go +++ b/internal/media/metadata.go @@ -75,7 +75,7 @@ func clearMetadata(ctx context.Context, filepath string) error { // terminateExif cleans exif data from file at input path, into file // at output path, using given file extension to determine cleaning type. func terminateExif(outpath, inpath string, ext string) (err error) { - var inFile *os.File + var inFile fileReader var outFile *os.File // Ensure handles diff --git a/internal/media/probe.go b/internal/media/probe.go index 5c07b04fb..47990eea3 100644 --- a/internal/media/probe.go +++ b/internal/media/probe.go @@ -22,7 +22,6 @@ import ( "encoding/binary" "image/jpeg" "io" - "os" "strings" "code.superseriousbusiness.org/gotosocial/internal/gtserror" @@ -80,7 +79,7 @@ func probe(ctx context.Context, filepath string) (*result, error) { // probeJPEG decodes the given file as JPEG and determines // image details from the decoded JPEG using native Go code. -func probeJPEG(file *os.File) (*result, error) { +func probeJPEG(file fileReader) (*result, error) { // Attempt to decode JPEG, adding back hdr magic. cfg, err := jpeg.DecodeConfig(io.MultiReader( @@ -129,7 +128,7 @@ func probeJPEG(file *os.File) (*result, error) { // // copied from github.com/disintegration/imaging // but modified to optimize discard operations. -func readOrientation(r *os.File) int { +func readOrientation(r fileReader) int { const ( markerAPP1 = 0xffe1 exifHeader = 0x45786966 diff --git a/internal/media/util.go b/internal/media/util.go index d73206434..fbd232daa 100644 --- a/internal/media/util.go +++ b/internal/media/util.go @@ -24,10 +24,13 @@ import ( "io/fs" "os" "path" + "runtime" + "syscall" "code.superseriousbusiness.org/gotosocial/internal/gtserror" "codeberg.org/gruf/go-bytesize" "codeberg.org/gruf/go-iotools" + "codeberg.org/gruf/go-mmap" ) // media processing tmpdir. @@ -82,15 +85,31 @@ func (af allowFiles) Open(name string) (fs.File, error) { // Ffmpeg likes to read containing // dir as '.'. Allow RO access here. case ".": - return openRead(file.dir) + return os.OpenFile(file.dir, os.O_RDONLY, 0) } } return nil, os.ErrPermission } +// MmapThreshold defines the threshold file size (in bytes) for which +// a call to OpenRead() will deem as big enough for a file to be worth +// opening using an `mmap` syscall. This is a runtime initialized number +// based on the number of available CPUs, as in concurrent conditions Go +// can make optimizations for blocking `read` syscalls which scales with +// the number of available goroutines it can have running at once. +var mmapThreshold = mmap.Threshold{At: int64(runtime.NumCPU() * syscall.Getpagesize())} + +// fileReader is a type alias to the interface{} that +// codeberg.org/gruf/go-mmap exposes, to make things a +// little less visually confusing. this interfaces{} +// abstracts away whether a (regular!) file has been +// opened via os.OpenFile(..., RDONLY) or has been +// mmapped into memory for access via byte slice. +type fileReader = mmap.FileReader + // openRead opens the existing file at path for reads only. -func openRead(path string) (*os.File, error) { - return os.OpenFile(path, os.O_RDONLY, 0) +func openRead(path string) (fileReader, error) { + return mmapThreshold.OpenRead(path) } // openWrite opens the (new!) file at path for read / writes. |
