Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

'Out of Memory' error when there are heavy assertion logs printed in Cypress Test Runner #23131

Closed
navdeepdevrepublic opened this issue Aug 5, 2022 · 17 comments
Assignees
Labels
stage: awaiting response Potential fix was proposed; awaiting response topic: aw snap 🙁

Comments

@navdeepdevrepublic
Copy link

Current behavior

Cypress Test runner crashes with error 'Out of Memory'.
OutOfMemoryError

Desired behavior

In this situation, Cypress should contract itself with 'Read more' or 'Read less' links in the assertion logs or if the cypress log is heavy it should dump the logs into local storage.

Test code to reproduce

The below line of code prints the complete JSON response from the API in the logs while asserting and hence the out of memory error occurs.
expect(JSON.stringify(resp1.body)).to.include('DynamicColumns')

Below is the complete code to reproduce:

File example.cy.js

cy.request('https://devxxx.office.nl/Grid/ApplyFilter').as('req1').then((resp1)=>{

                        //expect(JSON.stringify(resp1.body)).to.include('DynamicColumns')
                
                        cy.get('@req1').should('have.property', 'status', 200)
                    })

Cypress Version

10.3.1

Other

No response

@AtofStryker AtofStryker self-assigned this Aug 5, 2022
@cypress-bot cypress-bot bot added the stage: investigating Someone from Cypress is looking into this label Aug 5, 2022
@AtofStryker
Copy link
Contributor

Hi @navdeepdevrepublic. Thank you for opening an issue. This usually means that the browser has run out of memory. Have you tried giving the chrome process more memory? Also, is it possible you could provide a reproduction repo? I cannot seem to access that url you have provided.

@navdeepdevrepublic
Copy link
Author

Hi @AtofStryker I was looking more about the same issue and I found out this issue close to my problem #1906, At the end of this ticket #1906 , you can see, there are a few more people who are still facing this problem in cypress version 10.3.1, in my case, there are heavy cypress logs generated and I can see the memory taken by this test is close to 4 GB which is itself a huge, moreover talking about the URL which you are not able to access in my above sample code is because of that URL is VPN restricted.

Memory taken
image

In my above code if I am commenting this line //expect(JSON.stringify(resp1.body)).to.include('DynamicColumns') then my tests are running fine.

@AtofStryker
Copy link
Contributor

4GB is definitely quite a bit of memory. For diagnostics, have you tried increasing the memory of the process or is your machine maxed out on memory usage? Since the URL is VPN restricted, are you able to provide a reproduction that we can run to illustrate the problem?

My guess is that the request is quite large that you are asserting on, as are some of the others. Have you tried decreasing the numTestsKeptInMemory to lower than the default (which is 50)? This should free up some memory in the browser, but will reduce the amount of snapshots in memory.

@cypress-bot cypress-bot bot added stage: awaiting response Potential fix was proposed; awaiting response and removed stage: investigating Someone from Cypress is looking into this labels Aug 8, 2022
@Prashant-Kan
Copy link

Prashant-Kan commented Aug 8, 2022

Same problem since cypress v8.3
I think this requires urgent look
because its getting worse when we have to use numTestsKeptInMemory:0 every time

My machine is having high configuration (16 GB RAM, SSD and i7 10th generation processor).

I am looking of the solution other than numTestskeptInMemory.

@navdeepdevrepublic
Copy link
Author

navdeepdevrepublic commented Aug 9, 2022

@AtofStryker I am facing crash only when the JSON response gets printed (multiple times in the loop) in the test runner logs (while putting assertion), indeed the JSON response is heavy on which I am asserting.

Please guide me, how I can increase the memory of the process? (as you have written above)

I am unable to provide you with the URL to reproduce this issue.

The workaround numTestsKeptInMemory:0 is not working for me because I have only one test which has a loop for printing the multiple JSON responses.

@AtofStryker Do you know any way of asserting on JSON response without printing in the console or the JSON response could show in a compressed form in the logs?

@Georgi0304
Copy link

Georgi0304 commented Aug 9, 2022

I am also having the same issue. My test runs for about 8 minutes and then crashes with Aw, Snap! Error code: Out of Memory. I use numTestsKeptInMemory:0 and the memory footprint does not exceed 2,600,000K but it still crashes every time.
The strange thing is that one week ago my test was running fine for 23 mins and this week it cannot run for more than 8 mins

@AtofStryker
Copy link
Contributor

possibly related to #23193

@cypress-bot cypress-bot bot added stage: investigating Someone from Cypress is looking into this and removed stage: awaiting response Potential fix was proposed; awaiting response labels Aug 9, 2022
@AtofStryker
Copy link
Contributor

@navdeepdevrepublic sorry for the late reply. It has been a very busy few days. I don't think there is a direct way to provide the process with more memory, but out of curiosity, does the issue also happen when you are in run mode and how does it work with other browsers (for instance, electron)?

@navdeepdevrepublic
Copy link
Author

@AtofStryker Yes, I have tried in run mode also and with Chrome and Electron browser as well.

@navdeepdevrepublic
Copy link
Author

Users are still facing their issues in this ticket #1906

@rachelruderman
Copy link
Contributor

rachelruderman commented Aug 22, 2022

Hi @navdeepdevrepublic, can you provide a simple reproduction we can use to dig into this further? This will help us isolate where the issue is happening and help you faster 🙏 . You can use cypress-test-tiny to set it up

I tried to set up a repo with the test code provided but the URL does not work as expected. Manually navigating to the website and going to the network tab shows that it fails to load the response data:
Screen Shot 2022-08-21 at 11 59 40 PM

@cypress-bot cypress-bot bot added stage: awaiting response Potential fix was proposed; awaiting response and removed stage: investigating Someone from Cypress is looking into this labels Aug 22, 2022
@navdeepdevrepublic
Copy link
Author

@rachelruderman The above URL cannot be accessed at your end because it is VPN restricted URL. I am providing you an improvised version of code below. The below code picks up one DOM element and iterate its child elements in a loop and clicks on each element (which is itself a menu item) and on each click, the API is returning one JSON (quite long) which gets printed in the cy.log and then the error occurs.

This sample code to reproduce

  it('User should be able to verify the Global Master Data', () => {
    
    cy.visit(Cypress.env('fms_base_url')+'Home/Index')
    cy.wait(5000)

    //Check the length of the children of 'Global Master Data'
    new homePage().getMenuItem_GlobalMasterData().contains('Global Master Data').should('have.text','Global Master 
    Data').click().parent().find('ul').children().then((elements)=>{
      cy.log('length of elements -->  '+elements.length)
    })

    cy.wait(5000)

    // Click on each children of Global Master Data and verify if the data is being retrieved or not
    new homePage().getMenuItem_GlobalMasterData().contains('Global Master Data').should('have.text','Global Master 
    Data').parent().find('ul').children().each(($el, index, $list)=>{
      
        cy.wait(4000)
        
        let text11 = ''
        cy.wrap($el).invoke('text').then((txt)=>{
          text11 = txt
        }) 

        cy.wrap($el).click().wait(5000).invoke('attr','data-groupitem').then((valOfDataGroupItem)=>{

          cy.request(Cypress.env('fms_base_url')+'Grid/BindGridByID?ItemID='+valOfDataGroupItem+'&name='+text11.replace(' 
          ','%20')+'&catalog=Global%20Master%20Data&IsHLP=false&IsTabStrip=false').as('req').then((resp)=>{
          
          expect(JSON.stringify(resp.body)).to.include('DynamicColumns')
            
          cy.get('@req').should('have.property', 'status', 200)
          })
          
        })
      
    })

  })

@rachelruderman Hope the above code helps you to reproduce the issue, you just have to print the complete response returned by any API for multiple times in a loop in a spec file to reproduce this issue.

@rachelruderman
Copy link
Contributor

Hi @navdeepdevrepublic, sorry I missed that part about the VPN! I know this whole process can be frustrating and I thank for your patience. I'll put together a sample reproduction today. Would just like to clarify one part:

you just have to print the complete response returned by any API for multiple times in a loop

How many times is the loop running? The exact number would be helpful so I can ensure my reproduction does the same

@navdeepdevrepublic
Copy link
Author

@rachelruderman Thank you for your response. The loop has to print around 40+ different API responses in the test runner logs and the loop runs only once in one spec file.

@mike-plummer mike-plummer self-assigned this Aug 24, 2022
@mike-plummer
Copy link
Contributor

Simple reproduction case has been created here

@navdeepdevrepublic I was able to reproduce the issue you described above. I'm certain there are memory optimizations that could be made in the Cypress app to at least delay the failure, but there's also the potential that simple refactors in your test could also avoid the issue. I would like to have a better understanding on why you're doing the JSON.stringify method you've described - anytime we execute a string matcher the entirety of the string is (intentionally) output to the log which, if the string is very large, will have an impact on memory consumption. Is there potentially a more efficient set of assertions you could do that wouldn't involve matching on the entire stringified response?

I imagine you have some idea where in your JSON response the value you're looking for should exist - could you not pluck out the object keys, or a subset of the response and just match against that? This would not only improve your memory situation but would probably also speed up your tests (stringify and large string matches aren't cheap operations).

For example, if you're just validating that a given key exists in the response you could do something like this:

const responseKeys = Object.keys(response.body)
expect(responseKeys).to.include('DynamicColumns')

This would result in only outputting the keys (or some other subset) of the JSON response rather than the entire thing which would avoid the runaway memory consumption

@navdeepdevrepublic
Copy link
Author

@mike-plummer Thank you for the response, I have modified my tests and it is working fine as per the proposed solution, however this 'Out of Memory' issue has been reported by many other users as well, there could be the other user scenarios, in my case, it is manageable however in other cases, it might not be.

@nagash77
Copy link
Contributor

@navdeepdevrepublic at this point I am going to close this specific issue as I think we have come to a place with a solution that improves the test that was causing this issue. If you have other out of memory issues please do open a new ticket and we can investigate. Or feel free to search our backlog and add your voice to any of those open issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
stage: awaiting response Potential fix was proposed; awaiting response topic: aw snap 🙁
Projects
None yet
Development

No branches or pull requests

7 participants