For some reason, and I'm not sure why, my Processing sketch doesn't display in JavaScript mode. However, in Java mode it runs how it's intended. I'm pretty sure that everything used is in the Processing API, so I really have no idea why this doesn't work.
A rundown on the program. Basically, I had to create a Stock Ticker with text moving from bottom right of the screen to the left on a constant loop.
Stock Ticker:
Stock[] quotes = new Stock[12];
float t=0;
PFont text;
void setup() {
size(400,200);
//Importing "Times" font
text = createFont( "Times" ,18,true);
//Assigning Strings and Float values to Stock array index
quotes[0] = new Stock("ADBE",68.60);
quotes[1] = new Stock("AAPL",529.36);
quotes[2] = new Stock("ADSK",51.41);
quotes[3] = new Stock("CSCO",21.87);
quotes[4] = new Stock("EA",30.17);
quotes[5] = new Stock("FB",67.07);
quotes[6] = new Stock("GOOG",1201.52);
quotes[7] = new Stock("HPQ",31.78);
quotes[8] = new Stock("INTC",25.41);
quotes[9] = new Stock("MSFT",40.49);
quotes[10] = new Stock("NVDA",18.56);
quotes[11] = new Stock("YHOO",38.24);
//Assigning Position of indexs using setX method from Stock class
float x = 0;
for (int i = 0; i < quotes.length; i++)
{
quotes[i].getX(x);
x = x + (quotes[i].width());
}
t = x;
}
void draw() {
background(55);
//Rendering of Text using trans and show functions from Stock class
for (int i = 0; i < quotes.length; i++)
{
quotes[i].trans();
quotes[i].show();
}
//Transparent Rectangl;e
noStroke();
fill(10,10,10,127);
rect(0,164,width,35);
}
Stock:
class Stock {
String stockName;
float stockNum;
float x;
String show;
Stock(String n, float v)
{
stockName = n;
stockNum = v;
show = (stockName + " " + stockNum + " ");
}
//Sets position of each index
void getX(float x_)
{
x = x_;
}
//Moves text
void trans()
{
x = x - 1;
if (x < width-t)
{
x = width;
}
}
//Renders Text
void show()
{
textFont(text);
textAlign(LEFT);
fill(255);
text(show,x,height-10);
}
//Records and returns width of index
float width()
{
textFont(text);
return textWidth(show);
}
}
Two things:
According to Processing.js page, it does not work with most Java, so
you need to be careful with what libraries you use. From their
Quick Start page:
Processing.js is compatible with Processing, but is not, and will
never be, fully compatible with Java. If your sketch uses functions or
classes not defined as part of Processing, they are unlikely to work
with Processing.js. Similarly, libraries that are written for
Processing, which are written in Java instead of Processing, will most
likely not work.
Even if the libraries you use are supported, you have to be very
careful while naming your variables because Javascript being a
typeless language can result in variable name clashes that you
wouldn't normally worry about when writing in Processing in Java
mode (or in Java directly) since it is a typed language. See
Processing.js's note on this.
Related
I am following the textbook The Nature of code's Example 7.1. (The original code is written in Java, but since the processing library is functionally identical to p5.js, I have rewritten it JavaScript out of convenience)
I believe that I have copied the examples code verbatim, yet somehow I have ended up with a result which I did not expect. There is an incomplete portion in the Sierpinski's triangle which is displayed.
I would like to know where I am going wrong in my code, or what I might be misunderstanding to cause this kind of issue.
Here's the Code for the image
class CA {
constructor(ca_width) {
this.generation = 0;
this.w = 5;
this.cells = new Array(1050 / this.w);
this.newcells = new Array(this.cells.length);
this.ruleset = [0, 1, 0, 1, 1, 0, 1, 0]; // [1,1,0,1,1,1,1,0]//
for (let i = 0; i < this.cells.length; i++) {
this.cells[i] = 0;
}
this.cells[this.cells.length / 2] = 1;
}
generate() {
let nextgen = new Array(this.cells.length);
for (let i = 1; i < this.cells.length - 1; i++) {
let left = this.cells[i - 1];
let me = this.cells[i];
let right = this.cells[i + 1];
nextgen[i] = this.rules(left, me, right);
}
this.cells = nextgen;
this.generation++;
}
rules(a, b, c) {
let s = "" + a + b + c;
let index = parseInt(s, 2);
return this.ruleset[index];
}
display() {
for (let i = 0; i < this.cells.length; i++) {
if (this.cells[i] == 0)
fill(255);
else fill(0);
stroke(0);
rect(i * this.w, this.generation * this.w,
this.w, this.w);
}
}
}
let cA;
function setup() {
createCanvas(windowWidth, windowHeight);
cA = new CA(1000);
}
function draw() {
// createCanvas(windowWidth, 400);
// background(150);
cA.display();
cA.generate();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/1.4.1/p5.js"></script>
Based on your logic for computing the next generation, this.cells[0] and this.cells.at(-1) are always undefined, which is rendered as black. You might want to initialize these to 0, and possibly use a wraparound logic for computing their value (i.e. cells[0] = rule(cells.at(-1), cells[0], cells[1])).
I don't know what your Java code looks like, but if you're using a new int[] type, then that'll be zeroed out and probably work as expected, unlike JS Array().
In general, use caution with the Array() constructor in JS. It leaves the cells in an uninitialized state ("empty slots"), so you usually want to chain .fill(0) or spread/map it to make it a usable, unsurprising array that you'd expect such a constructor to emit, as it does in Java.
Keep in mind that the Nature of Code is available in a p5.js version, and there exist automatic translators from Processing to p5.js, like pde2js. Note that I haven't tried pde2js or the other translators but they seem worth a look.
Recently I came across the concept of hidden classes and inline caching used by V8 to optimise js code. Cool.
I understand that objects are represented as hidden classes internally. And two objects may have same properties but different hidden classes (depending upon the order in which properties are assigned).
Also V8 uses inline caching concept to directly check offset to access properties of object rather than using object's hidden class to determine offsets.
Code -
function Point(x, y) {
this.x = x;
this.y = y;
}
function processPoint(point) {
// console.log(point.x, point.y, point.a, point.b);
// let x = point;
}
function main() {
let p1 = new Point(1, 1);
let p2 = new Point(1, 1);
let p3 = new Point(1, 1);
const N = 300000000;
p1.a = 1;
p1.b = 1;
p2.b = 1;
p2.a = 1;
p3.a = 1;
p3.b = 1;
let start_1 = new Date();
for(let i = 0; i< N; i++ ) {
if (i%4 != 0) {
processPoint(p1);
} else {
processPoint(p2)
}
}
let end_1 = new Date();
let t1 = (end_1 - start_1);
let start_2 = new Date();
for(let i = 0; i< N; i++ ) {
if (i%4 != 0) {
processPoint(p1);
} else {
processPoint(p1)
}
}
let end_2 = new Date();
let t2 = (end_2 - start_2);
let start_3 = new Date();
for(let i = 0; i< N; i++ ) {
if (i%4 != 0) {
processPoint(p1);
} else {
processPoint(p3)
}
}
let end_3 = new Date();
let t3 = (end_3 - start_3);
console.log(t1, t2, t3);
}
(function(){
main();
})();
I was expecting results to be like t1 > (t2 = t3) because :
first loop : V8 will try to optimise after running twice but it will soon encounter different hidden class so it will de optimise.
second loop : same object is called all the time so inline caching can be used.
third loop : same as second loop because hidden classes are same.
But results are not satisfying. I got (and similar results running again and again) -
3553 4805 4556
Questions :
Why results were not as expected? Where did my assumptions go wrong?
How can I change this code to demonstrate hidden classes and inline caching performance improvements?
Did I get it all wrong from the starting?
Are hidden classes present just for memory efficiency by letting objects share them?
Any other sites with some simple examples of performance improvements?
I am using node 8.9.4 for testing. Thanks in advance.
Sources :
https://blog.sessionstack.com/how-javascript-works-inside-the-v8-engine-5-tips-on-how-to-write-optimized-code-ac089e62b12e
https://draft.li/blog/2016/12/22/javascript-engines-hidden-classes/
https://richardartoul.github.io/jekyll/update/2015/04/26/hidden-classes.html
and many more..
V8 developer here. The summary is: Microbenchmarking is hard, don't do it.
First off, with your code as posted, I'm seeing 380 380 380 as the output, which is expected, because function processPoint is empty, so all loops do the same work (i.e., no work) no matter which point object you select.
Measuring the performance difference between monomorphic and 2-way polymorphic inline caches is difficult, because it is not large, so you have to be very careful about what else your benchmark is doing. console.log, for example, is so slow that it'll shadow everything else.
You'll also have to be careful about the effects of inlining. When your benchmark has many iterations, the code will get optimized (after running waaaay more than twice), and the optimizing compiler will (to some extent) inline functions, which can allow subsequent optimizations (specifically: eliminating various things) and thereby can significantly change what you're measuring. Writing meaningful microbenchmarks is hard; you won't get around inspecting generated assembly and/or knowing quite a bit about the implementation details of the JavaScript engine you're investigating.
Another thing to keep in mind is where inline caches are, and what state they'll have over time. Disregarding inlining, a function like processPoint doesn't know or care where it's called from. Once its inline caches are polymorphic, they'll remain polymorphic, even if later on in your benchmark (in this case, in the second and third loop) the types stabilize.
Yet another thing to keep in mind when trying to isolate effects is that long-running functions will get compiled in the background while they run, and will then at some point be replaced on the stack ("OSR"), which adds all sorts of noise to your measurements. When you invoke them with different loop lengths for warmup, they'll still get compiled in the background however, and there's no way to reliably wait for that background job. You could resort to command-line flags intended for development, but then you wouldn't be measuring regular behavior any more.
Anyhow, the following is an attempt to craft a test similar to yours that produces plausible results (about 100 180 280 on my machine):
function Point() {}
// These three functions are identical, but they will be called with different
// inputs and hence collect different type feedback:
function processPointMonomorphic(N, point) {
let sum = 0;
for (let i = 0; i < N; i++) {
sum += point.a;
}
return sum;
}
function processPointPolymorphic(N, point) {
let sum = 0;
for (let i = 0; i < N; i++) {
sum += point.a;
}
return sum;
}
function processPointGeneric(N, point) {
let sum = 0;
for (let i = 0; i < N; i++) {
sum += point.a;
}
return sum;
}
let p1 = new Point();
let p2 = new Point();
let p3 = new Point();
let p4 = new Point();
const warmup = 12000;
const N = 100000000;
let sum = 0;
p1.a = 1;
p2.b = 1;
p2.a = 1;
p3.c = 1;
p3.b = 1;
p3.a = 1;
p4.d = 1;
p4.c = 1;
p4.b = 1;
p4.a = 1;
processPointMonomorphic(warmup, p1);
processPointMonomorphic(1, p1);
let start_1 = Date.now();
sum += processPointMonomorphic(N, p1);
let t1 = Date.now() - start_1;
processPointPolymorphic(2, p1);
processPointPolymorphic(2, p2);
processPointPolymorphic(2, p3);
processPointPolymorphic(warmup, p4);
processPointPolymorphic(1, p4);
let start_2 = Date.now();
sum += processPointPolymorphic(N, p1);
let t2 = Date.now() - start_2;
processPointGeneric(warmup, 1);
processPointGeneric(1, 1);
let start_3 = Date.now();
sum += processPointGeneric(N, p1);
let t3 = Date.now() - start_3;
console.log(t1, t2, t3);
Could somebody teach me how to restore a binary tree using Prorder and Inorder arrays. I've seen some examples (none in JavaScript) and they kind of make sense but the recursive call never returns a full tree when I try and write. Would love to see explanations as well. Here's some code to start off:
Creating a tree node uses this:
function Tree(x) {
this.value = x;
this.left = null;
this.right = null;
}
Creating the tree uses this:
function retoreBinaryTree(inorder, preorder) {
}
Some sample input:
inorder = [4,2,1,5,3]
preorder = [1,2,4,3,5,6]
inorder = [4,11,8,7,9,2,1,5,3,6]
preorder = [1,2,4,11,7,8,9,3,5,6]
EDIT I had been working on this for days and was unable to come up with a solution of my own so I searched some out (most were written in Java). I tried to mimic this solution but to no avail.
This is a solution in C++ which I think you could translate without problem:
/* keys are between l_p and r_p in the preorder array
keys are between l_i and r_i in the inorder array
*/
Node * build_tree(int preorder[], long l_p, long r_p,
int inorder[], long l_i, long r_i)
{
if (l_p > r_p)
return nullptr; // arrays sections are empty
Node * root = new Node(preorder[l_p]); // root is first key in preorder
if (r_p == l_p)
return root; // the array section has only a node
// search in the inorder array the position of the root
int i = 0;
for (int j = l_i; j <= r_i; ++j)
if (inorder[j] == preorder[l_p])
{
i = j - l_i;
break;
}
root->left = build_tree(preorder, l_p + 1, l_p + i,
inorder, l_i, l_i + (i - 1));
root->right = build_tree(preorder, l_p + i + 1, r_p,
inorder, l_i + i + 1, r_i);
return root;
}
I just started fiddling around with JavaScript. Coming from Java and OO PHP things are getting weirder with every step :)
This is my introduction project to javascript in which I've set out to program multiplayer working version of Settlers of Catan. Code below is an attempt to store cube coordinates of N sized hexagonal map tiles in an array.
I've read you declare object in javascript by assigning functions to variables.
var Tile = function (x, y, z) {
this.x = x;
this.y = y;
this.z = z;
};
var Map = function () {
var grid = [];
function generate_map(radius) {
for (width = -radius; width <= radius; width++) {
var r1 = Math.max(-radius, -width - radius);
var r2 = Math.min(radius, -width + radius);
for (r = r1; r <= r2; r++) {
grid.push(new Tile(width, r, -width - r));
}
}
}
};
I've tried instantiating new Map object, calling its only function and outprinting the resulting values stores in grid[] array. But for each loop is not playing nice :( I get the unexpected identifier.
var main = function () {
var basic_map = new Map();
basic_map.generate_map(3);
for each (var tile in basic_map.grid) {
console.log(tile.x, tile.y, tile.z);
}
};
main();
I am fully aware this is one of those face palm errors, but help would nevertheless be appreciated, cheers!
Change this:
function generate_map(radius) {
...to this:
this.generate_map = function(radius) {
Edit: there are actually more issues than I at first realized.... :)
A few other tips:
First, I would recommend changing:
var Tile = function (x, y, z) {
...to simply be:
function Tile(x, y, z) {
(the same goes for Map). Your current solution works fine, but it's not very idiomatic, and until ES6 there was nothing in the spec that would cause var Tile = function to cause the resulting function's 'name' property to be set to "Tile", which is useful when it comes to debugging. I recently wrote another answer that delves a bit more into the differences between, e.g., function Foo() {} and var Foo = function() {}.
Second, you probably want to rename Map to something else. Map is a core part of ES6 now (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map).
Third, even though you can create your generate_map function using this.generate_map, you may want to move it to the Map's prototype. Also, since you need to expose the grid value, you want to store it as a property, rather than a local variable scoped to the NewMapName constructor. E.g.,:
function NewMapName() {
this.grid = [];
}
NewMapName.prototype.generateMap = function(radius) {
// you can access the grid here via `this.grid`
...
};
By moving it to the prototype, that means all instances of NewMapName will share the same function reference, rather than it being created over-and-over-and-over (although maybe you really only create it once? Either way, it's more idiomatic, at a minimum). Note that I took some liberties with the "camelCasing" here (see the last point).
Fourth, your generateMap implementation is leaking some global variables (width and r, since you don't declare them with var). I would change that to this:
NewMapName.prototype.generateMap = function(radius) {
for (var width = -radius; width <= radius; width++) {
var r1 = Math.max(-radius, -width - radius);
var r2 = Math.min(radius, -width + radius);
for (var r = r1; r <= r2; r++) {
grid.push(new Tile(width, r, -width - r));
}
}
};
Fifth, your loop is kind of broken. I would refactor that as follows:
var main = function () {
var basicMap = new NewMapName();
basicMap.generateMap(3);
basicMap.grid.forEach(function(tile) {
console.log(tile.x, tile.y, tile.z);
});
};
main();
Lastly, and probably most minor, is that in JavaScript-land, camelCase is far more dominant that snake_case, so generate_map might be "better" as generateMap.
As can be seen in the screenshots at the bottom of the question or by going
directly to the game.
text is placed differently dependent on browser (firefox 15.0.1 renders differently then IE 9.9 and Chrome 21).
call to draw function:
context.fillText(this.wlines[i], this.xcoord, this.ycoord + y + (t) * this.sizey);
constructor of object:
function textItem(text, xcoord, ycoord, sizex, sizey,style, context) {
this.wlines = [];
this.text = text;
this.xcoord = xcoord;
this.ycoord = ycoord;
this.sizex = sizex;
this.sizey = sizey;
this.style = style;
if (text == null) {
text = "";
}
var lines = text.split("~");
// this is first line text
context.save();
if (this.style < 3) {
context.shadowOffsetY = 2;
context.font = 'bold 18px "palatino linotype"';
} else if (this.style == 4) {
this.font = '16px "palatino linotype"';
this.shadowOffsetX = 2;
this.shadowOffsetY = 1;
this.shadowColor = "rgba(255,255,255,1)";
}
if (this.style == 5) {
this.wlines.push(text);
} else {
for (j = 0; j < lines.length; j += 1) {
var words = lines[j].split(" ");
var lastLine = "";
var l = sizex;
var measure = 0;
for (i = 0; i < words.length; i += 1) {
var w = words[i];
measure = context.measureText(lastLine + w).width;
if (measure < l) {
lastLine += (w + " ");
} else {
//this is body text
if (this.style == 6) {
lastLine += "...";
}
this.wlines.push(lastLine);
lastLine = (w + " ");
if (this.style < 3) {
context.font = 'bold 14px "palatino linotype"';
}
}
if (i == words.length - 1) {
this.wlines.push(lastLine);
break;
}
}
}
}
context.restore();
}
text,xcoorc,ycoord,xsize,ysize are parsed from an xml file. The compond name in this example:
<sizex>196</sizex>
<sizey>20</sizey>
<xcoord>383</xcoord>
<ycoord>14</ycoord>
style is a defined value based on the text effects desired and context is the 2d context of the canvas to draw on (for layering effects).
As shown all values are exactly the same between browsers. The only check I do between browsers is
<meta http-equiv="x-ua-compatible" content="ie=edge,chrome=1"/>
in the header of the html page.
I really don't know where the line height discrepancy is coming from and any help on the matter would be appreciated.
The line height discrepancy changes depending on the text but not in a manner that I have figured out yet. If there is any information that I have omitted please don't hesitate to ask.
ff:
ff screen http://www.sunshinecompound.com/images/firefoxscreen.png
Chrome:
chrome screen http://www.sunshinecompound.com/images/googlescreen.png
Update The solution for my program at least was to build use an offset. Further I got huge performance boosts by creating the text object and then saving the text object as an image. In FF which was the browser with the greatest slowdown I saw a little bit over a 5X decrease in overall program run-time. This is despite having to recreate the text object each time text dynamically changed in the program (I change dynamic counters per second and mouse hover effects every 200ms but with the performance I'm currently getting I can probably improve that to 100ms).
Yep.
It's placed differently, scaled differently, kerned differently, aliased differently and even measured differently (as in measureText) between browsers.
If you need pixel consistency for your game then you're going to have to use images instead of text. Sorry. :(
The only way to make measureText consistent is to pre-compute.
The only way to make fillText consistent is to use images instead of text. It's must faster, anyway.
Both of these are untenable if the text is extremely dynamic, but if you only ever write say, less than 100 different pieces of text in your app, images are probably your best bet.
Otherwise, you could use a pixel font generated from an image (use drawImage with each letter or common word) and hope for OK performance, caching the longer, common strings.