Need Help Debugging - Firefox consumes all my ram


(David '-1' Schmid) #1

Hello there!

I was testing my server for problems and uncovered a problem with the firefox “developer edition”, not sure if other versions are affected, but I’m confident they will be.
I’m posting this here, since I cannot figure out what the problem is exactly or how to start debugging.

I don’t need help figuring out my problem: there is a problem in firefox and I don’t know how to find it.

Pretext

I’m running a server that clients (browsers) can connect to via websockets.
When a client sends a string, the server will search its backend for items matching the particular string, just very basic search functionality.

Setup

Backend

(just for completeness, not very relevant): I’m using Apache solr as a backend. The backend will stream JSON for all the matches it found. These results can be quite large, so I’ve built a stack-machine that will parse the stream and converts it to complete JSON objects while the stream is still coming in. Similar to pull-parsing xml.

As an example, this is a triple that will be received by the client:

{"id": "c4a19bbf330f31900d8ac20c995400ec34bb0f37", 
 "title": "Choline and betaine consumption lowers cancer risk: a meta-analysis of epidemiologic studies", 
 "doi": "10.1038/srep35547"}

So while my backend is still processing the response, these results will be received by the client, just to keep the whole thing responsive and less intensive on the client.

Otherwise clients would have to wait for the server to finish, then receive and parse (possibly huge) JSON response. It will also save resources on the server, since I can shed all allocated RAM for already sent objects.

Frontend

So, the frontend is extremely simple:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8"/>
        <title>Chat Room</title>
    </head>
    <body>
        <textarea id="chat-log" cols="100" rows="20"></textarea><br/>
        <input id="chat-message-input" type="text" size="100"/><br/>
        <input id="chat-message-submit" type="button" value="Send"/>
    </body>
    <script>
        var roomName = "asd";

        var chatSocket = new WebSocket(
            'ws://' + window.location.host +
            '/ws/chat/' + roomName + '/');

        chatSocket.onmessage = function(e) {
            var data = JSON.parse(e.data);
            var message = data['message'];
            document.querySelector('#chat-log').value += (message + '\n');
        };

        chatSocket.onclose = function(e) {
            console.error('Chat socket closed unexpectedly');
        };

        document.querySelector('#chat-message-input').focus();
        document.querySelector('#chat-message-input').onkeyup = function(e) {
            if (e.keyCode === 13) {  // enter, return
                document.querySelector('#chat-message-submit').click();
            }
        };

        document.querySelector('#chat-message-submit').onclick = function(e) {
            var messageInputDom = document.querySelector('#chat-message-input');
            var message = messageInputDom.value;
            chatSocket.send(JSON.stringify({
                'message': message
            }));

            messageInputDom.value = '';
        };
    </script>
    </html>

which will result in this (after one query):
2018-10-01-085916_670x416_scrot

You send the name of an author of some academic publication and will receive all document ids and their respective title and DOI.

All of this works quite well, pushing 1000 results like this does not cause any problems.

The Problem

The problem surfaces, when I search for authors with a common name, here “Wei Wang” will result in 16407 objects like this.
This will consume all of my 32GB of RAM, if I’m lucky my kernel will kill the offending process, resulting in a crashed firefox tab.

I’ve tried chromium, they just consume mostly CPU, memory usage is well below a few 100 MB. Chromium will receive something short of 16200 results and then kill the process.

Obvious Culprit?

document.querySelector('#chat-log').value += (message + '\n');

Sure. Appending these consecutive results to a string is neither efficient, nor sane. But I expected my server to crash and burn, not firefox.

So, yes. I’m not creating a well-behaving app here. But I should not be able to send firefox into oblivion like this.

edit: I’ve replaced this with logging the messages to the console, I’m experiencing dropped messages, now.

My question

Is this a problem with websockets or is the JS engine misbehaving? I’m unsure where to start and look for problems since it either works or freezes my machine.

How can I go about this?

I’m on firefox developer edition 63.0b8 (64-bit).
I’ll happily provide more information to track this down :smiley:

best regards,
-1


(Boris Zbarsky) #2

If you can modify the server output a bit to use a bunch of memory but not quite enough to crash Firefox, you could use about:memory to generate a report of what’s using memory.