improve (efficiency): improve memory efficiency for resource intensive tasks

This commit is contained in:
Mickael Kerjean
2019-05-06 15:16:57 +10:00
parent 284d554a67
commit 2feed9127e
4 changed files with 67 additions and 18 deletions

View File

@ -24,6 +24,8 @@ var (
ErrFilesystemError = NewError("Can't use filesystem", 503) ErrFilesystemError = NewError("Can't use filesystem", 503)
ErrMissingDependency = NewError("Missing dependency", 424) ErrMissingDependency = NewError("Missing dependency", 424)
ErrNotAuthorized = NewError("Not authorized", 401) ErrNotAuthorized = NewError("Not authorized", 401)
ErrCongestion = NewError("Traffic congestion, try again later", 500)
ErrTimeout = NewError("Timeout", 500)
) )
type AppError struct { type AppError struct {

View File

@ -3,8 +3,10 @@ plg_image_light rely on a few libraries for:
- image resizing: libresize.a: a library built on top of libvips - image resizing: libresize.a: a library built on top of libvips
To create the libraries to be used by Filestash: To create the libraries to be used by Filestash:
```
./create_libtranscode.sh ./create_libtranscode.sh
./create_libresize.sh ./create_libresize.sh
```
To test the libraries are working fine: To test the libraries are working fine:
``` ```

View File

@ -10,25 +10,50 @@ import (
. "github.com/mickael-kerjean/filestash/server/common" . "github.com/mickael-kerjean/filestash/server/common"
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
"io" "io"
"time"
"unsafe" "unsafe"
) )
var VIPS_LOCK = semaphore.NewWeighted(int64(10)) const (
THUMBNAIL_TIMEOUT = 5 * time.Second
THUMBNAIL_MAX_CONCURRENT = 50
)
var VIPS_LOCK = semaphore.NewWeighted(THUMBNAIL_MAX_CONCURRENT)
func CreateThumbnail(t *Transform) (io.ReadCloser, error) { func CreateThumbnail(t *Transform) (io.ReadCloser, error) {
VIPS_LOCK.Acquire(context.Background(), 1) ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(THUMBNAIL_TIMEOUT))
defer cancel()
if err := VIPS_LOCK.Acquire(ctx, 1); err != nil {
return nil, ErrCongestion
}
defer VIPS_LOCK.Release(1) defer VIPS_LOCK.Release(1)
filename := C.CString(t.Input) imageChannel := make(chan io.ReadCloser, 1)
defer C.free(unsafe.Pointer(filename)) go func() {
var buffer unsafe.Pointer filename := C.CString(t.Input)
len := C.size_t(0) len := C.size_t(0)
if C.image_resize(filename, &buffer, &len, C.int(t.Size), boolToCInt(t.Crop), C.int(t.Quality), boolToCInt(t.Exif)) != 0 { var buffer unsafe.Pointer
return nil, NewError("", 500) if C.image_resize(filename, &buffer, &len, C.int(t.Size), boolToCInt(t.Crop), C.int(t.Quality), boolToCInt(t.Exif)) != 0 {
C.free(unsafe.Pointer(filename))
imageChannel <- nil
return
}
C.free(unsafe.Pointer(filename))
buf := C.GoBytes(buffer, C.int(len))
C.g_free(C.gpointer(buffer))
imageChannel <- NewReadCloserFromBytes(buf)
}()
select {
case img := <- imageChannel:
if img == nil {
return nil, ErrNotValid
}
return img, nil
case <- ctx.Done():
return nil, ErrTimeout
} }
buf := C.GoBytes(buffer, C.int(len))
C.g_free(C.gpointer(buffer))
return NewReadCloserFromBytes(buf), nil
} }
func boolToCInt(val bool) C.int { func boolToCInt(val bool) C.int {

View File

@ -8,10 +8,16 @@ import (
"context" "context"
"golang.org/x/sync/semaphore" "golang.org/x/sync/semaphore"
. "github.com/mickael-kerjean/filestash/server/common" . "github.com/mickael-kerjean/filestash/server/common"
"time"
"unsafe" "unsafe"
) )
var LIBRAW_LOCK = semaphore.NewWeighted(int64(5)) const (
TRANSCODE_TIMEOUT = 10 * time.Second
TRANSCODE_MAX_CONCURRENT = 5
)
var LIBRAW_LOCK = semaphore.NewWeighted(int64(TRANSCODE_MAX_CONCURRENT))
func IsRaw(mType string) bool { func IsRaw(mType string) bool {
switch mType { switch mType {
@ -45,14 +51,28 @@ func IsRaw(mType string) bool {
} }
func ExtractPreview(t *Transform) error { func ExtractPreview(t *Transform) error {
LIBRAW_LOCK.Acquire(context.Background(), 1) ctx, cancel := context.WithDeadline(context.Background(), time.Now().Add(TRANSCODE_TIMEOUT))
defer cancel()
if err := LIBRAW_LOCK.Acquire(ctx, 1); err != nil {
return ErrCongestion
}
defer LIBRAW_LOCK.Release(1) defer LIBRAW_LOCK.Release(1)
filename := C.CString(t.Input) transcodeChannel := make(chan error, 1)
defer C.free(unsafe.Pointer(filename)) go func() {
filename := C.CString(t.Input)
defer C.free(unsafe.Pointer(filename))
if err := C.image_transcode_compute(filename, C.int(t.Size)); err != 0 {
transcodeChannel <- ErrNotValid
}
transcodeChannel <- nil
}()
if err := C.image_transcode_compute(filename, C.int(t.Size)); err != 0 { select {
return ErrNotValid case err := <- transcodeChannel:
return err
case <- ctx.Done():
return ErrTimeout
} }
return nil
} }