How to optimize my heroku webapp - node.js

I'm new to web development and I'm currently in the process of building my own website for my portfolio. My app uses node, express, and Heroku to launch it online. However, the page isn't as smooth as I'd like it to be. It drops a lot of frames when scrolling and viewing animations. I'm wondering what I can do to make my app feel buttery smooth. I've looked all around for solutions but I'm too new to development to really understand what to do. I've attempted to use the inspector to see if the css or javascript files are slowing down the processes via the waterfall insepctor, but came up dry. So far, I've compressed the files and lowered the scale of all images. Also, the entire website is static content so I can't imagine why its running so slowly. Any help would be much appreciated.
The website in question

The "lag" could be caused by the ScrollFire plugin. Every time you call Materialize.scrollFire(..) you actually add a JavaScript listener for the "scroll" event. The way you use it, you call Materialize.scrollFire for each of your target objects, so you actually create multiple "scroll" listeners. But the scrollFire options is actually an array of targets, so you could get away with only initializing it once. Like so:
var options = [
{selector: '.iphone1', offset: 300, callback: function(el) {
$('.iphone1').css('visibility', 'visible');
$('.iphone1').addClass('animated slideInLeft');
}},
{selector: '#paragraph_intro', offset: 300, callback: function(el) {
$('#paragraph_intro').css('visibility', 'visible');
$('#paragraph_intro').addClass('animated slideInRight');
}},
// ... And so on
];
Materialize.scrollFire(options);
It could also be caused by your own scroll listener at:
$(window).on('scroll', function(){
updateNavigation();
changeNavColor();
changeHeaderColor();
});
I would consider adding some kind of throttling, so these functions are called less frequent while the user is scrolling.
These may not be the problem, or the whole problem, as I cannot see how the page would behave without it, but it could have an impact, so it's worth investigating.

Related

Severe memory leaks in the Autodesk Forge viewer on devices

I'm developing an Angular/ Typescript application that makes use of the Autodesk Forge viewer to display building models on smartphones and tablets. The application itself runs smoothly, but the problem occurs when I close the application. After closing the application, I notice that hardly any memory gets released, as can be seen in the image below (I close the application around the 8 seconds mark) and after opening the viewer for two or three more times it will run out of memory and crash.
When I close the application, I call both the tearDown() and the finish() method as described in the Forge docs and set all possible references to the Forge viewer to null, but they memory leak still persists. This is the main chunk of my viewer code:
this.initOptions = {
path: 'url to model',
env: 'Local',
useADP: false,
extensions: [],
};
Autodesk.Viewing.Initializer(this.initOptions, () => {
this.onEnvInitialized();
});
private onEnvInitialized() {
this.viewer = new Autodesk.Viewing.Private.GuiViewer3D(this.viewerContainer.nativeElement, {});
this.viewer.initialize();
this.viewer.loadModel(this.initOptions.path, {}, (doc) => {
// further forge viewer execution here
}, (errorMsg) => {
console.log(errorMsg);
});
}
public ngOnDestroy() {
// remove all eventlisteners
this.initOptions = null;
this.viewer.tearDown();
this.viewer.finish();
this.viewer = null;
}
Is this a known issue and/ or is there some way I can manually release the memory used by the Forge viewer after closure? (It is part of the use case that I have to be able to open more than three viewers after each other in one session.)
Update [19-09-17]
I tried opening my viewer in a fresh, empty angular2 project, and although less memory is being used in general, the same behavoir of not clearing the memory still applies, as can be seen here. I do notice that the event listeners are drastically reduced now. I also updated the Forge Viewer to version 2.17, and the same issue still applies here as well.
The problem remains with version 3.3.5 of the forge viewer. The issue however seems a bit deeper. It looks like when calling viewer.finish() it doesn't release any GPU memory used for the textures.
We call this function everytime you navigate away from the page with the viewer as angular destroys the canvas in the DOM. I would expect .finish to also remove the textures from the memory. Is there any other function that can be called to completely unload any model and textures?
Here are some screenshots where you can see the memory buildup.
Initial initialisation of the page
after returning to this page after closing it
after returning to this page after closing it a third time
What version of the Viewer are you currently using? Here you can see a list of the recent changes on the viewer version, v2.17 has a Memory Limit ON by default.
https://developer.autodesk.com/en/docs/viewer/v2/overview/changelog/
Also the version of the viewer can be checked if it is not been defined from the console by typing LMV_VIEWER_VERSION

Grab an image from willOutputSampleBuffer or related?

So, Brad Larson is awesome. I'm using his GPUImage library since he optimized the CGContextCreateImage for video output to instead render straight into OpenGL. Then he rewrote it to be even more amazing, and half the questions are outdated. The other half have the new callbacks, Like this question, but for the life of me, I can't get the video frames callback to not be nil. (the CMSampleBuffer to CIImage functions)
I know I have to "tag the next frame" to be kept in memory, thanks to his blog. I also know I process it (but GPUImageVideo also does that), then I grab from the framebuffer. Still nill.
The capture command that's supposed to auto-filter it into a CGImage, from the CGImagePicture's processImageUpToFilter function seems to be what I want, and I've seen it mentioned, but I am lost as to how to hook up the output to its frameBuffer.
Or should I use GPUImageRawDataOutput, and how to hook up? I've been copying and pasting, editing, experimenting, but unsure if it's just the fact I don't know openGL enough to hook up the right stuff or?
Any help is appreciated. I wouldn't ask, since so many related questions are up here, but I use them and still get nil on the output.
Here is my current try:
func willOutputSampleBuffer(sampleBuffer: CMSampleBuffer!) {
gpuImageVideoCamera.useNextFrameForImageCapture()
//Next line seems like a waste, as this func is called in GPUImageVideoCamera already.
gpuImageVideoCamera.processVideoSampleBuffer(sampleBuffer);
if let image = gpuImageVideoCamera.imageFromCurrentFramebuffer()
{
//it's nil
}
}
It seems to use the filter instead, and useNextFrame should be AFTER processing to not go super-slow.
Inside of willOutputSampleBuffer, this is it.
if let image = transformFilter.imageFromCurrentFramebuffer()
{
// image not nil now.
}
transformFilter.useNextFrameForImageCapture(); //enusre this comes after
This has given us stunning speeds that beat Google's p2p library. Brad, thanks, everyone should support your efforts.

NodeJS large directory file changes

I am working on more of a security dashboard, it watches for changes in files in the entire home directory with hundreds of sites (all Joomla, so a lot of files).
In order to keep on top of potential security issues we want to watch for file changes in an efficient way without creating unnecessary CPU/Memory overhead. We want to watch it at a faster interval but I know its more of a balancing act when you do want to keep it from using more cpu then a side process should.
I have tried to use "watch" with the following code, running in the home directory:
var watch, fs;
watch = require('watch');
fs = require('fs');
watch.createMonitor(__dirname,{interval:500,filter:function(file,stat){
if(file.indexOf('index.php')!=-1){
return true;
}else{
return false;
}
}},function(monitor){
monitor.filter(function(file){
console.log(file);
})
monitor.on('created',function(file,stat){
console.log(file + ' new');
});
monitor.on('changed',function(file,stat){
console.log(file + ' changed');
});
monitor.on('removed',function(file,stat){
console.log(file + ' deleted');
});
});
However this spikes the CPU to over 100% of a single core (sometimes 2) out of 8. Memory also takes up about 20% of 8gb pretty quickly as well. This is all just to create the watch event on all the files, so its before it can actually detect any file changes.
I know the issue with this is it goes through each file individually, and only does not track it if you filter that sort of file. Typically all I need to watch is the index.php in every directory, down to a point that it could be consistent (with some exceptions).
Is there a module already built to do this? Or is this something new? All modules I find assume its a smaller directory (like watching LESS or something) So not built for this sort of application at all.
Any ideas? I know this code will need to be scrapped as there is no way I can see to stop the CPU overhead.
Do not use package 'watch', just use fs.watch(...)
package 'watch':
consistent APIs
very slow because implement mostly in node, look source to see how it work
souce code: https://github.com/mikeal/watch/blob/master/main.js
fs.watch(..)
non-consistent APIs, not all OSs are supported.
very fast because it reused OS features
document: http://nodejs.org/docs/latest/api/fs.html#fs_fs_watch_filename_options_listener

Remove and restore Scope from digest cycles

Is there a way to remove a scope from the digest cycles? In other words, to suspend/resume a scope digest cycle?
In my case, I have all pages already loaded, but not all of them visible. So I'd like to suspend the ones that aren't visible to avoid useless processing. I don't want to use ng-view + $route, I don't want/need deep-linking.
I saw this thread and arrived to this fiddle. It probably does the work, but it's pretty invasive and not very framework-update-friendly.
Is there any other solution like a $scope.suspend() and scope.resume()? Or a less invasive one (from framework perspective)? I'm currently thinking about $destroy and $compile cycles.
I've ran into the same problem and I found an interesting solution that doesn't interfere (too much) with AngularJS. Add this to the scopes you want to disable:
var watchers;
scope.$on('suspend', function () {
watchers = scope.$$watchers;
scope.$$watchers = [];
});
scope.$on('resume', function () {
scope.$$watchers = watchers;
watchers = null;
});
Then, you can disable a scope and its children with: scope.$broadcast('suspend') and bring it back with scope.$broadcast('resume').
As the framework stands today there are no methods to suspend / resume digest on a scope. Having said this there are several techniques that one can use to limit number of watches that are executed as part of a digest cycle.
First of all, if parts of a screen are hidden anyway you could use the ng-switch family of directives thus removing invisible parts completely from the DOM.
Secondly, if a digest cycle is triggered from your directive via $apply and you want to limit watches re-evaluation to child scopes you could call $digest instead of $apply.
Then, yes, one could destroy and re-create scopes as described in the discussion you've linked to. But, if you are already hiding parts of the DOM it sounds like ng-switch might be a better option.

How to attach mouse event listeners to embedded nsIWebBrowser in C++

I've embedded an nsIWebBrowser in my application. Because I'm just generating HTML for it on the fly, I'm using OpenStream, AppendToStream, and CloseStream to add content. What I need is to add event listeners for mouse movement over the web browser as well as mouse clicks. I've read documentation and tried lots of different things, but nothing I have tried has worked. For instance, the code below would seem to do the right thing, but it does nothing:
nsCOMPtr<nsIDOMWindow> domWindow;
mWebBrowser->GetContentDOMWindow(getter_AddRefs(domWindow));
if (!mEventTarget) {
mEventTarget = do_QueryInterface(domWindow);
if (mEventTarget)
mEventTarget->AddEventListener(NS_LITERAL_STRING("mouseover"), (nsIDOMEventListener *)mEventListener, PR_FALSE);
}
Perhaps it isn't working because this is run during initialization, but before any content is actually added. However, if I add it during AppendStream, or CloseStream, it segfaults.
Please tell me a straightforward way to do this.
Well, here's the answer:
nsCOMPtr<nsIDOMEventTarget> cpEventTarget;
nsCOMPtr<nsIDOMWindow> cpDomWin;
m_pWebBrowser->GetContentDOMWindow (getter_AddRefs(cpDomWin));
nsCOMPtr<nsIDOMWindow2> cpDomWin2 (do_QueryInterface (cpDomWin));
cpDomWin2->GetWindowRoot(getter_AddRefs(cpEventTarget));
rv = cpEventTarget->AddEventListener(NS_LITERAL_STRING("mousedown"),
m_pBrowserImpl, PR_FALSE);

Resources