diff --git a/c_src/Makefile b/c_src/Makefile index 9d5b782..bb9541a 100644 --- a/c_src/Makefile +++ b/c_src/Makefile @@ -66,6 +66,7 @@ calling_from_make: cd .. && mix compile all: install + @echo > /dev/null install: $(PREFIX) $(VIX) diff --git a/c_src/vips_operation.c b/c_src/vips_operation.c index 37f9404..ba3c170 100644 --- a/c_src/vips_operation.c +++ b/c_src/vips_operation.c @@ -556,6 +556,37 @@ ERL_NIF_TERM nif_vips_cache_get_max_mem(ErlNifEnv *env, int argc, return enif_make_uint64(env, vips_cache_get_max_mem()); } +ERL_NIF_TERM nif_vips_leak_set(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + ASSERT_ARGC(argc, 1); + + ErlNifUInt64 value = 0; + + if (!enif_get_uint64(env, argv[0], &value)) { + return raise_badarg(env, "Failed to integer value"); + } + + if (value != 0) { + vips_leak_set(TRUE); + } else { + vips_leak_set(FALSE); + } + + return ATOM_OK; +} + +ERL_NIF_TERM nif_vips_tracked_get_mem(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + ASSERT_ARGC(argc, 0); + return enif_make_uint64(env, vips_tracked_get_mem()); +} + +ERL_NIF_TERM nif_vips_tracked_get_mem_highwater(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]) { + ASSERT_ARGC(argc, 0); + return enif_make_uint64(env, vips_tracked_get_mem_highwater()); +} + ERL_NIF_TERM nif_vips_shutdown(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]) { ASSERT_ARGC(argc, 0); diff --git a/c_src/vips_operation.h b/c_src/vips_operation.h index 6e47bef..2f1aee3 100644 --- a/c_src/vips_operation.h +++ b/c_src/vips_operation.h @@ -42,6 +42,15 @@ ERL_NIF_TERM nif_vips_cache_set_max_mem(ErlNifEnv *env, int argc, ERL_NIF_TERM nif_vips_cache_get_max_mem(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); +ERL_NIF_TERM nif_vips_leak_set(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +ERL_NIF_TERM nif_vips_tracked_get_mem(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + +ERL_NIF_TERM nif_vips_tracked_get_mem_highwater(ErlNifEnv *env, int argc, + const ERL_NIF_TERM argv[]); + ERL_NIF_TERM nif_vips_shutdown(ErlNifEnv *env, int argc, const ERL_NIF_TERM argv[]); diff --git a/c_src/vix.c b/c_src/vix.c index f9f5bcb..761ea0c 100644 --- a/c_src/vix.c +++ b/c_src/vix.c @@ -114,6 +114,9 @@ static ErlNifFunc nif_funcs[] = { {"nif_vips_cache_get_max_files", 0, nif_vips_cache_get_max_files, 0}, {"nif_vips_cache_set_max_mem", 1, nif_vips_cache_set_max_mem, 0}, {"nif_vips_cache_get_max_mem", 0, nif_vips_cache_get_max_mem, 0}, + {"nif_vips_leak_set", 1, nif_vips_leak_set, 0}, + {"nif_vips_tracked_get_mem", 0, nif_vips_tracked_get_mem, 0}, + {"nif_vips_tracked_get_mem_highwater", 0, nif_vips_tracked_get_mem, 0}, {"nif_vips_version", 0, nif_vips_version, 0}, {"nif_vips_shutdown", 0, nif_vips_shutdown, 0}, {"nif_vips_nickname_find", 1, nif_vips_nickname_find, 0}, diff --git a/lib/vix/nif.ex b/lib/vix/nif.ex index f7cbee8..67d066b 100644 --- a/lib/vix/nif.ex +++ b/lib/vix/nif.ex @@ -121,6 +121,15 @@ defmodule Vix.Nif do def nif_vips_cache_get_max_mem, do: :erlang.nif_error(:nif_library_not_loaded) + def nif_vips_leak_set(_integer), + do: :erlang.nif_error(:nif_library_not_loaded) + + def nif_vips_tracked_get_mem, + do: :erlang.nif_error(:nif_library_not_loaded) + + def nif_vips_tracked_get_mem_highwater, + do: :erlang.nif_error(:nif_library_not_loaded) + def nif_vips_version, do: :erlang.nif_error(:nif_library_not_loaded) diff --git a/lib/vix/vips.ex b/lib/vix/vips.ex index 28ed02a..376ecb3 100644 --- a/lib/vix/vips.ex +++ b/lib/vix/vips.ex @@ -77,6 +77,34 @@ defmodule Vix.Vips do Nif.nif_vips_cache_get_max_mem() end + @doc """ + Turn on or off vips leak checking + """ + @spec set_vips_leak_checking(boolean()) :: :ok + def set_vips_leak_checking(bool) when is_boolean(bool) do + Nif.nif_vips_leak_set(if bool, do: 1, else: 0) + end + + @doc """ + Returns the number of bytes currently allocated by libvips. + + Libvips uses this figure to decide when to start dropping cache. + """ + @spec tracked_get_mem() :: integer() + def tracked_get_mem do + Nif.nif_vips_tracked_get_mem() + end + + @doc """ + Returns the largest number of bytes simultaneously allocated via libvips. + + Handy for estimating max memory requirements for a program. + """ + @spec tracked_get_mem_highwater() :: integer() + def tracked_get_mem_highwater do + Nif.nif_vips_tracked_get_mem_highwater() + end + @doc """ Get installed vips version """ diff --git a/test/vix/vips_test.exs b/test/vix/vips_test.exs new file mode 100644 index 0000000..7b27c32 --- /dev/null +++ b/test/vix/vips_test.exs @@ -0,0 +1,24 @@ +defmodule Vix.VipsTest do + use ExUnit.Case, async: true + + alias Vix.Vips + alias Vix.Vips.Image + + import Vix.Support.Images + + test "tracked_get_mem/0" do + {:ok, im} = Image.new_from_file(img_path("puppies.jpg")) + {:ok, _bin} = Image.write_to_buffer(im, ".png") + + usage = Vips.tracked_get_mem() + assert is_integer(usage) && usage > 0 + end + + test "tracked_get_mem_highwater/0" do + {:ok, im} = Image.new_from_file(img_path("puppies.jpg")) + {:ok, _bin} = Image.write_to_buffer(im, ".png") + + usage = Vips.tracked_get_mem_highwater() + assert is_integer(usage) && usage > 0 + end +end