Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delete Javascript blobs?

I'm having a heck of a time getting rid of these stupid things. I've got a couple of Chrome apps that deal with lots of media files; one of them I was able to use a bunch of "delete"s and a window.URL.revokeObjectURL that finally stopped them from building up in chrome://blob-internals/, but this other one, nothing seems to help. Am I missing something? I know exactly when I'm done with the damn thing, but there seems to be nothing I can do.

Specifically, I'm using a File object in a block like this:

ref.file(function(f) {
    // Do some stuff...
    // and now I'm done!
    delete f
});

Here's the actual source of my app:

https://github.com/pkulak/photo-importer

and here's the one where I think I actually solved the problem, but who really knows:

https://github.com/pkulak/drive-slideshow

like image 581
Phil Kulak Avatar asked Apr 06 '14 20:04

Phil Kulak


People also ask

Can I delete BLOBs?

The Delete Blob operation marks the specified blob or snapshot for deletion. The blob is later deleted during garbage collection. Note that in order to delete a blob, you must delete all of its snapshots. You can delete both at the same time with the Delete Blob operation.

How do I delete blob files?

To delete a blob, call either of these methods: Delete. DeleteAsync. DeleteIfExists.

What are JavaScript BLOBs?

The Blob object represents a blob, which is a file-like object of immutable, raw data; they can be read as text or binary data, or converted into a ReadableStream so its methods can be used for processing the data. Blobs can represent data that isn't necessarily in a JavaScript-native format.

Where are BLOBs stored JavaScript?

A Blob is stored in the memory much like any other ArrayBuffer . It's stored in the ram, just like the other objects declared in the window. Looking at the chrome://blob-internals , we can see how its physically stored in the ram.


1 Answers

This looks like you have a memory leak.

JavaScript doesn't have a "delete" in the sense you're talking about, it garbage collects as properties and variables become orphaned. The delete operator is one such way to achieve that - it removes the definition of a property from an Object.
Using delete correctly means using it on a property, not a variable. The reason it works on some variables is because of what happens with var in the global namespace (i.e. they become properties of window). This also means you can't delete a parameter.

Further, note that once a function has finished invoking, if there are no references being kept alive then all of it's internals will be GC'd.

Next, consider

var o = {};
o.a = [];
o.b = o.a;
delete o.a;

What is o.b now?

`o.b; // []`

It's still pointing at the Array even though we deleted the o.a reference. This means that the Array won't be garbage collected.

So what does this mean for you?

To get rid of your Blobs, you need to destroy all the references to them.

Yes, revoking the URI is part of it, but you also need to remove references all the way through your code. If you're finding this difficult, I'd suggest you wrap all your Blobs so you can at least minimise the problem.

var myBlob = (function () {
    var key, o;
    function myBlob(blob) {
        var url;
        this.blob = blob;
        blob = null;
        this.getURL = function () {
            if (url) return url;
            return url = URL.createObjectURL(this.blob);
        };
        this.dispose = function () {
            if (url) url = URL.revokeObjectURL(url), undefined;
            this.blob = null;
        };
    }
    o = new Blob();
    for (key in o)
        (function (key) {
            Object.defineProperty(myBlob.prototype, key, {
                enumerable: true,
                configurable: true,
                get: function () {return this.blob[key];}
            });
        }(key));
    o = key = undefined;
    return myBlob;
}());

Now, instead of your regular Blob creation use new myBlob(blob) immediately as you make your blob, keeping no other references to the blob. Then when you're finished with your Blob, call myWrappedBlob.dispose(); and it should free it up to be GC'd. If it's really necessary to pass the Blob into something directly, I gave it the property myBlob.blob.

like image 192
Paul S. Avatar answered Sep 21 '22 22:09

Paul S.