-
Notifications
You must be signed in to change notification settings - Fork 918
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
refactor(BaseClass): reduces amount of created objects/functions #1613
Conversation
Please provide more information. The prof of reduce memory and improve speed up. And why did you remove the hash code property? |
I haven't removed Object.defineProperty(this, 'hashCode', { value: Math.floor(Date.now() * Math.random()) }) Update:
www/BaseArrayClass.js:5: BaseClass.apply(this);
www/TileOverlay.js:13: BaseClass.apply(this);
www/GroundOverlay.js:11: BaseClass.apply(this);
www/Circle.js:13: BaseClass.apply(this);
www/Marker.js:14: BaseClass.apply(this);
www/KmlOverlay.js:11: BaseClass.apply(this);
www/Polyline.js:13: BaseClass.apply(this);
www/Map.js:29: BaseClass.apply(self);
www/Polygon.js:13: BaseClass.apply(this);
www/HtmlInfoWindow.js:11: BaseClass.apply(self); So, the simplest calculation: Currently all functions were moved into prototype. That means they are reused across all instances. The last time I saw such optimization in knockout.js and at that time they gain ~50% of performance (objects created faster because code doesn't create functions in constructor, functions created only once). |
And also you should not change the method name, bindTo(). And also did you test this code does not affect any current code, even multiple maps? I believe you created safe test code a lot. I can not accept your pull request soon. Please provide more information. |
The hashcode property is my mistake. Did you create unit test, of course? BaseClass is just JS code. You can test only this class on browser, of Node.js. |
I did brief testing. This is the most simple event emitter. However I will add unit tests for |
Test is really important especially for pull request. In general (I'm not pointting only you), Especially you are trying to make a big change. Unit test has to include two side:
Thank you for your preparation. |
I know that it's important but I don't see any tests in this repository ;) |
I do in my local, but I can not share them. If you send me a more public test, I appreciate for you. |
By the way, you should not use the name as Because you are not official. Since this plugin adapts the Apache License 2.0, I don't mind if you change the code, and redistribute it, but the plugin name is not good. This leads people who reached to your repo to misunderstand. At least you should change the name if you want to use the version 3.0 |
And one more by the way. |
I know but you should understand me as well: I don't want to spend a lot of time doing screenshots and calculating metrics. Better to spend it optimizing code, adding features or tests, real unit tests :) |
As I wrote, your code effect or affect the code overall. If this pull request improves the performance significantly in safe, I will pay some amount for your work. So what I want to know:
If you are tired today, you can do later. |
Git commit 02cc173, but I only replaced the I got an error with this simple code... var div = document.getElementById("map_canvas");
var map = plugin.google.maps.Map.getMap(div);
map.one(plugin.google.maps.event.MAP_READY, function() {
var htmlInfoWindow = new plugin.google.maps.HtmlInfoWindow();
var html = [
'This is <b>Html</b> InfoWindow',
'<br>',
'<button onclick="javascript:alert(\'clicked!\');">click here</button>',
].join("");
htmlInfoWindow.setContent(html);
map.addMarker({
position: {lat: 0, lng: 0},
draggable: true
}, function(marker) {
marker.on(plugin.google.maps.event.MARKER_CLICK, function() {
htmlInfoWindow.open(marker);
});
marker.trigger(plugin.google.maps.event.MARKER_CLICK);
});
}); at HTMLInfoWindow.trigger (BaseClass.js:64) at HTMLInfoWindow. (HtmlInfoWindow.js:170) at HTMLInfoWindow.trigger (BaseClass.js:64) at HTMLInfoWindow.calculate (HtmlInfoWindow.js:154) at HTMLInfoWindow.trigger (BaseClass.js:64) |
And do not remove the As I wrote, I designed this plugin is similar with the Google Maps JavaScript API v3.
I think I wrote to you before in another thread, please consider |
Since you removed map.addEventListener(plugin.google.maps.event.MAP_READY, function() {
}); As you can see, if you think Making a change to BaseClass means you are trying to make very big impact. That's why I'm asking |
I checked half of examples of the official demo app I haven't checked performance. Without the proof and fixing the error of HTMLInfoWindow, I can not accept your pull request. |
fair enough. I will check that use case, add it to unit tests and will update PR. Thanks for the help with testing! I will add back |
@wf9a5m75 by the way, thanks for suggestion to pay me but I don't need this. Just include my nickname in release notes and this will be enough. Thanks |
I found the issue, it can be fixed on You will find: self.on(event.INFO_OPEN); So, the question why is |
I used Timeline for refactored As you can see Scripting part for refactored Hope this is enought to proof that this code is faster. |
Utilizes prototype & Symbol instead of closure
Thank you for testing. |
And do you have a paypal account? If no, please tell me the best way to receive some amount for you? Please send me the information to my e-mail address. |
}, | ||
|
||
get: function(key) { | ||
return this[VARS_FIELD].hasOwnProperty(key) ? this[VARS_FIELD][key] : null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be return this[VARS_FIELD].hasOwnProperty(key) ? this[VARS_FIELD][key] : undefined
.
The null === undefined always false.
I sent you some amount to your e-mail from my paypal account. Please follow the instruction. |
var index = topic.push(listener); | ||
var self = this; | ||
|
||
return function() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you tell me why do you return this function?
function() {
self.off(eventName, listener)
}
I think this is not common way...
map.on(plugin.google.maps.event.MAP_READY, onMapReady)();
it's much easier to work with subscriptions than with callbacks. Lets imagine that you need to subscribe some function change event and afterwards when component or object is destroyed - unsubscribe it. Then you will do something like this: class Component {
constructor(input) {
this.input = input
this.changeListener = () => { console.log('changed!') }
this.input.on('change', this.changeListener)
}
onDestroy() {
this.input.off('change', this.changeListener)
}
} You need to store listener function in class instance. It's not very convenient especially when your function is big or just a wrapper for another function (e.g., Instead it's more convenient (and more logically) to store reference to a class Component {
constructor(input) {
this.input = input
this.unsubscribe = this.input.on('change', () => { console.log('changed!') })
}
onDestroy() {
this.unsubscribe()
}
} Code is cleaner. Who uses such appoach:
|
This is not the way I designed. |
In order to unsubscribe easily, I provide |
Sorry, but according to Google Trends, rxjs and knockoutjs are not so popular. https://trends.google.com/trends/explore?q=ionic,rxjs,knockoutjs,cordova https://trends.google.com/trends/explore?date=today%205-y&q=ionic,rxjs,knockoutjs,cordova So if I am forced to choose make a choice, I definitely choose And |
Actually I have to make a choice to support the ionic-native/google-maps wrapper plugin currently. |
How do you want to use I agree about knockout, but rxjs became popular when Angular2 was release and Ionic2 is built on top of Angular2. |
The problem of the wrapper plugin is which uses For example: this.map.one(GoogleMapsEvent.READY, () => {
for (let i = 0; i < locations.length; i++) {
this.map.addMarker(locations[i], this.onMarkerAdded);
}
});
onMarkerAdded(marker: Marker) {
marker.on(GoogleMapsEvent.MARKER_CLICK, this.onMarkerClick);
}
onMarkerClick(...params: any[]) {
let latLng = params[0];
let marker = params[1];
marker.showInfoWindow();
} In order to use write like the above code, But Currently, the JS plugin passes the marker instance for all marker events. Ionic does not allow this way
In order to solve this problem, the plugin passes the instance as the second argument. goal
However, this plugin does not support
Otherwise, this code would become like this:
So I'm planing to use the
The ionic wrapper plugin keeps the same method names as the JS plugin. I need to detect the Observable is available or not, but if the JS plugin supports Promise and Observable both, the benefit is big for ionic users. Hence I need to return something:
And you may notice that the JS plugin currently returns their instance of the class. Marker.prototype.setFlat = function(flat) {
flat = common.parseBoolean(flat);
this.set('flat', flat);
return this;
};
Marker.prototype.setIcon = function(url) {
if (url && common.isHTMLColorString(url)) {
url = common.HTMLColor2RGBA(url);
}
this.set('icon', url);
return this;
}; I designed this allows you to use the chain method like jquery.
I forgot to return
I understand your point, but as I write previously, this plugin supports three ways You just keep the callback if you want to remove particular event listener.
or simply just
|
And this code create different closures every time.
It means if you create 1,000 markers, this code creates another 1,000 closures. Did you say this is bad performance, didn't you? |
ok, it makes sense |
Utilizes prototype & Symbol instead of closure. This speeds up creation of overlays on map (markers, polygons, etc) and reduces amount of used memory.
Changes:
Symbol
if availablebindTo
, replaced it withsync
mehoddestroy
which callsoff
andempty