We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi guys,
I made several Python versions of 2d metaball sketches I found here on the forum or on the CodingTrain Github.
Problem: It runs super slow (<1fps !) while all Java versions run very smoothly (60fps).
Questions:
Why such a difference in the framerates ?
Is is possible to improve the Python code or am i for ever doomed for having chosen Python mode over Java mode ?
original JAVA code
main tab:
Blob[] blobs = new Blob[10];
void setup() {
size(640, 360);
colorMode(HSB);
for (int i = 0; i < blobs.length; i++) {
blobs[i] = new Blob(random(width), random(height));
}
}
void draw() {
background(51);
println(frameRate);
loadPixels();
for (int x = 0; x < width; x++) {
for (int y = 0; y < height; y++) {
int index = x + y * width;
float sum = 0;
for (Blob b : blobs) {
float d = dist(x, y, b.pos.x, b.pos.y);
sum += 10 * b.r / d;
}
pixels[index] = color(sum, 255, 255);
}
}
updatePixels();
for (Blob b : blobs) {
b.update();
//b.show();
}
}
blob class
class Blob {
PVector pos;
float r;
PVector vel;
Blob(float x, float y) {
pos = new PVector(x, y);
vel = PVector.random2D();
vel.mult(random(2, 5));
r = random(120, 400);
}
void update() {
pos.add(vel);
if (pos.x > width || pos.x < 0) {
vel.x *= -1;
}
if (pos.y > height || pos.y < 0) {
vel.y *= -1;
}
}
void show() {
noFill();
stroke(0);
strokeWeight(4);
ellipse(pos.x, pos.y, r*2, r*2);
}
}
PYTHON code
liste = []
def setup():
size(640, 360, FX2D)
colorMode(HSB)
[liste.append(Blob(random(width), random(height))) for e in range(10)]
def draw():
loadPixels()
for x in range(width):
for y in range(height):
index = x + y * width
sum = 0
for e in liste:
d = dist(x, y, e.pos.x, e.pos.y)
try:
sum += 10 * e.r / d
except ZeroDivisionError:
return 1
pixels[index] = color(sum, 255, 255)
updatePixels()
for e in liste:
e.update()
class Blob(object):
def __init__(self, x, y):
self.pos = PVector(x, y)
self.velocity = PVector.random2D()
self.velocity.mult(random(2, 5))
self.r = random(120, 400)
def update(self):
self.pos.add(self.velocity)
if self.pos.x > width or self.pos.x < 0:
self.velocity.x *= -1
if self.pos.y > height or self.pos.y < 0:
self.velocity.y *= -1
Answers
try looks slow, why not use if
in processing java we can use set instead of pixels and skip load and updatepixels
Hi Chrisir, thanks for your answer. The 'if' statement doesn't improve a bit the performance, unfortunately. What I don't get is why such a difference in the framerates. It's well known that Python mode runs slower than Java (around 20% slower if I recall correctly) but here we're talking major difference (nearly 100%) !
Regarding the
set()
function, the Processing documentation indicates:Not sure if they're talking performance wise...
Looks like a Lava lamp
The best I could figure out:
setup()
functiond
)With 2 tiny metaballs on a skimmed 640*360 canvas I can get up to 23 fps.
With 10, I'm still running at 1 fps or lower... ridiculous, really.
I tried
set()
yesterday in java instead ofpixels[]
and it was fasterI also tried int instead of float but it was slower
(I would have thought differently)
I tried as well as you suggested but in Python mode it runs a tiny bit slower... at least on my computer.
@solub --
How much is "a tiny bit"? That might be expected when running on Jython, right? Earlier you said:
Hi Jeremy,
With
set()
the sketch is running at 19/20 fps against 21/22 fps withloadPixels()
. Again this is with a skimmed 640*360 canvas and only 2 metaballs.As soon as I increase the pixel density (full or larger canvas) or the number of metaballs, the frame rate drops drastically (6/8 fps, then 1 fps).
So far, the biggest improvement was to move
loadPixels()
within thesetup()
function (preventing the pixels to be loaded at each iteration). The sketch then gained 4 fps (lol).Interesting. Yes, the difference between the originals (even after dropping the "try") is extremely dramatic. Perhaps something to do with the cost of explicit int vs. implicit float math operations -- or just Jython overhead? Not sure.
@JonathanFeinberg might have some idea why.
I tend to think it has to do with some Jython overhead... not sure about the explicit int vs implicit float math operations.
There are a couple of reasons why the way Jython was implemented on JVM has ended up so slow. :(
I know at least these 3 below: :-&
volatile
. Meaning the JVM gotta make sure each variable access is synchronized in memory.I see.
To be honest I really love both Processing and Python. Developping a Python mode for Processing was a great idea and the more I learn about programing and creative coding, the more I wish Processing could run native Python.
There are some other Processing / Python projects in the works... check out p5py from last year's GSOC 2017.
I'm a really big fan of the Jython (Python 2.7) Processing mode. It doesn't have great performance, but you can still do amazing things with it, despite its very particular limitations and constraints.
See also the GSOC 2018 proposal: https://forum.processing.org/two/discussion/26778/proposal-gsoc-2018-application-arihant-parsoya-native-python-and-processing
Thanks Jeremy!
So I found a way to display 10+ metaballs at 60fps on a large canvas using:
(the stroke is supposed to be black, the yellow color is a glitch from the gif conversion)
Unfortunately, I couldn't find a way to fill the blobs...