libvips/php-vips

Overwriting same file does not work

FluffyDiscord opened this issue · 4 comments

Hi, I am trying to overwrite the same file that is loaded and it always ends up corrupted or simply empty.

Example

<?php

use Jcupitt\Vips\Image;

require_once __DIR__."/vendor/autoload.php";

$image = Image::newFromFile("image.png");
$image->writeToFile("image.png"); // fails/writes empty/corrupted file
$image->writeToFile("image_under_different_name.png"); // works fine

Is this intentional ? Also can I manually close file handles? I am using RoadRunner which makes my app partially statefull and things creep up over time.

I am aware that I can disable file handler cache completely using Config::cacheSetMaxFiles(0) but that's not really a solution

Hello @FluffyDiscord,

I am trying to overwrite the same file that is loaded and it always ends up corrupted or simply empty.

This is not supported. libvips is a streaming image processing library. so it reads from the input in parallel with writing to the output, and tries not to hold entire images in memory. This means you can't write to the file you are reading from.

You could copy the input to memory, perhaps:

$image = Image::newFromFile("image.png")->copy_memory();
$image->writeToFile("image.png");

But of course you will lose one of libvips's advantages by doing this.

Also can I manually close file handles? I am using RoadRunner which makes my app stateless and things creep up over time.

I would guess this is memory fragmentation. Have you tried jemalloc?

Also can I manually close file handles? I am using RoadRunner which makes my app stateless and things creep up over time.

I would guess this is memory fragmentation. Have you tried jemalloc?

I have never heard of it.

It depends on your platform, but if it's based on glibc, the memory allocator is optimised for speed in lightly threaded systems. Long-lived and highly threaded programs will suffer with memory fragmentation over time, and will stabilize at perhaps 2x or more of the actual memory used.

Allocators like jemalloc are slightly slower, but much better at preventing fragmentation, and much better at returning unused memory to the host OS.