Git Product home page Git Product logo

Comments (17)

HexDecimal avatar HexDecimal commented on May 30, 2024

I actually have a rigged up benchmark script at "dev/stressTest.py" but it's very primitive and is currently configured to run in a profiling environment which slows it down significantly.

Also while I try to make the library cross-platform, I only have Windows and Linux computers to test on and have mostly just made the assumption that it still runs on Mac. It's worked before but I think it has a bad libpng.dylib file that has trouble with some PNG formats. There's also the fact that libtcod itself never had any official Mac support. The dylib's are something I grabbed from and old forum post from others trying to get it to work.

About performance, it's quite slow. But if you're not doing much it in it then it's fast enough. The problem is that Python itself is slow and type checking and conversion are not one if it's strong points. My drawing functions in TDL accept a broad array of types and making sure they fit in ctypes is difficult to do quickly. Still, I've done lots of work on my inner loops so the bigger operation you use (drawing a long string over drawing many characters) the faster it works. You'll always have to keep in mind that in Python every line of code is precious, and that it's likely to be slow no matter what you do.

I'll see about making some proper benchmarks. I like the idea of knowing the characters per second of the library.

Looking it up it seems that a cross-platform curses for Python is in a weird state. Running Python in Cygwin seems to have the best unicode support. And some other ports of curses have bizarre license choices. I don't really see distributing any of these to be an option including Cygwin.

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

Finished a benchmark script the tests the slower parts of the library, you can find it here:
https://github.com/HexDecimal/python-tdl/blob/master/dev/benchmark.py

Here are my results using Python 3:

Benchmark run on Sun Jun 14 04:38:47 2015
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
192000 tiles drawn in 4.50 seconds, 42.67 characters/ms, 11.11 FPS
192000 tiles drawn in 4.48 seconds, 42.87 characters/ms, 11.17 FPS
192000 tiles drawn in 4.49 seconds, 42.72 characters/ms, 11.13 FPS

Running Benchmark_DrawChar_NoColor
192000 tiles drawn in 4.31 seconds, 44.55 characters/ms, 11.60 FPS
192000 tiles drawn in 4.32 seconds, 44.44 characters/ms, 11.57 FPS
192000 tiles drawn in 4.30 seconds, 44.64 characters/ms, 11.62 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 4.36 seconds, 88.13 characters/ms, 22.95 FPS
384000 tiles drawn in 4.40 seconds, 87.27 characters/ms, 22.73 FPS
384000 tiles drawn in 4.44 seconds, 86.42 characters/ms, 22.51 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 4.57 seconds, 84.06 characters/ms, 21.89 FPS
384000 tiles drawn in 4.60 seconds, 83.44 characters/ms, 21.73 FPS
384000 tiles drawn in 4.57 seconds, 83.98 characters/ms, 21.87 FPS

Python 2 has near similar results.

And my results using PyPy:

Benchmark run on Sun Jun 14 04:53:00 2015
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
192000 tiles drawn in 3.49 seconds, 55.00 characters/ms, 14.32 FPS
192000 tiles drawn in 2.58 seconds, 74.53 characters/ms, 19.41 FPS
192000 tiles drawn in 2.55 seconds, 75.26 characters/ms, 19.60 FPS

Running Benchmark_DrawChar_NoColor
192000 tiles drawn in 2.45 seconds, 78.24 characters/ms, 20.37 FPS
192000 tiles drawn in 2.30 seconds, 83.37 characters/ms, 21.71 FPS
192000 tiles drawn in 2.27 seconds, 84.77 characters/ms, 22.08 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 5.37 seconds, 71.51 characters/ms, 18.62 FPS
384000 tiles drawn in 4.69 seconds, 81.86 characters/ms, 21.32 FPS
384000 tiles drawn in 4.65 seconds, 82.62 characters/ms, 21.51 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 2.17 seconds, 176.71 characters/ms, 46.02 FPS
384000 tiles drawn in 1.60 seconds, 239.55 characters/ms, 62.38 FPS
384000 tiles drawn in 1.72 seconds, 223.26 characters/ms, 58.14 FPS

I also wrote a Conway's Game of Life example inspired by the curses one:
https://github.com/HexDecimal/python-tdl/blob/master/examples/life.py
Hopefully this can give you an idea of how well the library performs, whether or not it's fast enough depends on whatever you're trying to make.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

Very low FPS here. It might be because of OpenGL. I don't know why the bitmap copy operation is so sluggish there. Are there any other backends?

Benchmark run on Sun Jun 14 16:32:37 2015
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor

Benchmark run on Sun Jun 14 16:40:23 2015
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
192000 tiles drawn in 14.51 seconds, 13.23 characters/ms, 3.45 FPS
192000 tiles drawn in 15.35 seconds, 12.51 characters/ms, 3.26 FPS
192000 tiles drawn in 15.09 seconds, 12.73 characters/ms, 3.31 FPS

Running Benchmark_DrawChar_NoColor
192000 tiles drawn in 16.42 seconds, 11.69 characters/ms, 3.04 FPS
192000 tiles drawn in 14.35 seconds, 13.38 characters/ms, 3.48 FPS
192000 tiles drawn in 13.85 seconds, 13.86 characters/ms, 3.61 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 13.56 seconds, 28.32 characters/ms, 7.37 FPS
384000 tiles drawn in 15.09 seconds, 25.45 characters/ms, 6.63 FPS
384000 tiles drawn in 13.53 seconds, 28.38 characters/ms, 7.39 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 14.21 seconds, 27.03 characters/ms, 7.04 FPS
384000 tiles drawn in 14.13 seconds, 27.18 characters/ms, 7.08 FPS
384000 tiles drawn in 15.77 seconds, 24.35 characters/ms, 6.34 FPS

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

Yes, in benchmark.py you can change the line:

RENDERER = 'OpenGL'

to

RENDERER = 'SDL'

Here's my benchmark of Python 3 in SDL:

Benchmark run on Sun Jun 14 07:34:09 2015
3840 characters/frame
Opened console in SDL mode
Running Benchmark_DrawChar_DefaultColor
192000 tiles drawn in 4.33 seconds, 44.35 characters/ms, 11.55 FPS
192000 tiles drawn in 4.32 seconds, 44.48 characters/ms, 11.58 FPS
192000 tiles drawn in 4.28 seconds, 44.86 characters/ms, 11.68 FPS

Running Benchmark_DrawChar_NoColor
192000 tiles drawn in 4.14 seconds, 46.37 characters/ms, 12.08 FPS
192000 tiles drawn in 4.13 seconds, 46.54 characters/ms, 12.12 FPS
192000 tiles drawn in 4.12 seconds, 46.64 characters/ms, 12.15 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 4.04 seconds, 95.09 characters/ms, 24.76 FPS
384000 tiles drawn in 4.02 seconds, 95.61 characters/ms, 24.90 FPS
384000 tiles drawn in 4.02 seconds, 95.61 characters/ms, 24.90 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 4.24 seconds, 90.65 characters/ms, 23.61 FPS
384000 tiles drawn in 4.23 seconds, 90.69 characters/ms, 23.62 FPS
384000 tiles drawn in 4.24 seconds, 90.56 characters/ms, 23.58 FPS

If it's still slow then it's likely Python becoming CPU bound. You'll need a fast single core to get good performance out of it. The CPU I tested has 4 cores that run at 1200MHz.

PyPy uses a JIT compiler which sometimes helps. The life.py example runs at around ~11 FPS in Python. In PyPy it eventually runs at ~60 FPS after a lot of stuttering while the JIT warms up.

In the end you might end up stuck with the same problem I had. Which is that it's sometimes too much to ask a high level scripting language to do too many low level things. There are workarounds, but they usually have trade offs.

You could consider learning Javascript and using rot.js. It's cross-platform and can do what you'd expect from a roguelike toolkit. Being a scripting language it will still have speed issues but they won't be as bad as this library in Python.

The library itself has opportunities to become faster but I've always prioritized portability and ease-of-use over speed. Something like Cython might work, but it will take a long time to get any results.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

SDL makes 10%-20% improvements, especially for Draw16 tests. It is interesting if switching to CFFI instead of ctypes can improve this further?

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

The life.py and benchmark.py worth shipping in tdl.bench namespace. The life may need to get FPS counter for that, though.

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

CFFI and ctypes are basically the same thing. I think PyPy is somehow able to take advantage of CFFI but I don't think there will be much of a performance benefit in regular Python.

If I was able to use Cython I'd be able to compile the Python drawing calls with the libtcod library calls. With the draw calls compiled it would remove most of the Python overhead and in theory run at a decent speed. And after the code is finished I should be able to distribute precompiled versions easily. This is my current plan.

Already added a FPS counter to the title bar in the life.py script.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

I don't know what is "compiled draw calls", but CFFI does compile calls into C libs into some compressed format, which should be faster.

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

Looks like CFFI can compile arbitrary helper C code after all. I'll see if I can get it set up.

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

Here's the current benchmark with TDL using a CFFI wrapper in Python 3:

Benchmark run on Mon Jun 15 05:00:26 2015
Running under CPython 3.4.1
In debug mode
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
192000 tiles drawn in 3.32 seconds, 57.76 characters/ms, 15.04 FPS
192000 tiles drawn in 3.29 seconds, 58.44 characters/ms, 15.22 FPS
192000 tiles drawn in 3.29 seconds, 58.37 characters/ms, 15.20 FPS

Running Benchmark_DrawChar_NoColor
192000 tiles drawn in 3.31 seconds, 58.06 characters/ms, 15.12 FPS
192000 tiles drawn in 3.30 seconds, 58.11 characters/ms, 15.13 FPS
192000 tiles drawn in 3.31 seconds, 58.07 characters/ms, 15.12 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 2.85 seconds, 134.59 characters/ms, 35.05 FPS
384000 tiles drawn in 2.86 seconds, 134.49 characters/ms, 35.02 FPS
384000 tiles drawn in 3.23 seconds, 118.84 characters/ms, 30.95 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 3.47 seconds, 110.53 characters/ms, 28.78 FPS
384000 tiles drawn in 3.47 seconds, 110.78 characters/ms, 28.85 FPS
384000 tiles drawn in 3.41 seconds, 112.50 characters/ms, 29.30 FPS

It's around 50% faster. This is without any extra optimizations added to the code.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

Guys at http://morepypy.blogspot.com/ will be happy to hear that. So, if you're going to make a post, it will be much appreciated. Especially if it will include nifty textmode art. =)

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

I might consider making a post, but I'm not really an ASCII artist.

Setting cffi up for distribution as been much harder than setting it up to compile. I've been having a hard time updating cffi on most of my Python installations. And I probably won't be able to develop it across as many versions of Python as I used for a while.

That said, it's very close to a finished state at this point. My C functions use simpler types so I was able to take out the more elaborate type code from the Python modules. It's a big deal as before I needed to convert colors into a struct while now I just use an int.

Here's the current benchmark for Python 3, the speed up is mostly from removed assert statements:

Benchmark run on Thu Jun 18 06:48:43 2015
Running under CPython 3.4.1
In debug mode
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
384000 tiles drawn in 2.95 seconds, 129.99 characters/ms, 33.85 FPS
384000 tiles drawn in 2.91 seconds, 132.13 characters/ms, 34.41 FPS
384000 tiles drawn in 2.91 seconds, 131.86 characters/ms, 34.34 FPS
384000 tiles drawn in 2.92 seconds, 131.72 characters/ms, 34.30 FPS

Running Benchmark_DrawChar_NoColor
384000 tiles drawn in 2.94 seconds, 130.43 characters/ms, 33.97 FPS
384000 tiles drawn in 2.96 seconds, 129.77 characters/ms, 33.79 FPS
384000 tiles drawn in 2.97 seconds, 129.20 characters/ms, 33.65 FPS
384000 tiles drawn in 3.01 seconds, 127.61 characters/ms, 33.23 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 2.60 seconds, 147.97 characters/ms, 38.53 FPS
384000 tiles drawn in 2.62 seconds, 146.72 characters/ms, 38.21 FPS
384000 tiles drawn in 2.62 seconds, 146.50 characters/ms, 38.15 FPS
384000 tiles drawn in 2.59 seconds, 148.31 characters/ms, 38.62 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 2.57 seconds, 149.58 characters/ms, 38.95 FPS
384000 tiles drawn in 2.58 seconds, 148.66 characters/ms, 38.71 FPS
384000 tiles drawn in 2.57 seconds, 149.52 characters/ms, 38.94 FPS
384000 tiles drawn in 2.53 seconds, 152.07 characters/ms, 39.60 FPS

Eventually I got it to run in PyPy again, the speedup for this was quite absurd:

Benchmark run on Thu Jun 18 06:50:52 2015
Running under PyPy 2.7.10
In debug mode
3840 characters/frame
Opened console in OpenGL mode
Running Benchmark_DrawChar_DefaultColor
384000 tiles drawn in 0.74 seconds, 519.62 characters/ms, 135.32 FPS
384000 tiles drawn in 0.61 seconds, 625.41 characters/ms, 162.87 FPS
384000 tiles drawn in 0.63 seconds, 611.46 characters/ms, 159.24 FPS
384000 tiles drawn in 0.60 seconds, 643.22 characters/ms, 167.50 FPS

Running Benchmark_DrawChar_NoColor
384000 tiles drawn in 0.64 seconds, 598.13 characters/ms, 155.76 FPS
384000 tiles drawn in 0.59 seconds, 645.38 characters/ms, 168.07 FPS
384000 tiles drawn in 0.59 seconds, 646.46 characters/ms, 168.35 FPS
384000 tiles drawn in 0.57 seconds, 671.33 characters/ms, 174.83 FPS

Running Benchmark_DrawStr16_DefaultColor
384000 tiles drawn in 0.97 seconds, 396.28 characters/ms, 103.20 FPS
384000 tiles drawn in 0.78 seconds, 492.31 characters/ms, 128.21 FPS
384000 tiles drawn in 0.74 seconds, 518.92 characters/ms, 135.14 FPS
384000 tiles drawn in 0.72 seconds, 534.82 characters/ms, 139.28 FPS

Running Benchmark_DrawStr16_NoColor
384000 tiles drawn in 0.85 seconds, 451.23 characters/ms, 117.51 FPS
384000 tiles drawn in 0.73 seconds, 525.31 characters/ms, 136.80 FPS
384000 tiles drawn in 0.70 seconds, 548.57 characters/ms, 142.86 FPS
384000 tiles drawn in 0.67 seconds, 569.73 characters/ms, 148.37 FPS

At this point I'm just trying to get a release ready. I don't have proper tests for most of the features other than the drawing functions so it's taking a while to make sure everything is moved to the cffi interface.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

Setting cffi up for distribution as been much harder than setting it up to compile. I've been having a hard time updating cffi on most of my Python installations. And I probably won't be able to develop it across as many versions of Python as I used for a while.

What is the biggest problem with that? I can see the pain, but I don't see the reason. Does distribution requires installed CFFI? Does CFFI make developing for multiple Python versions harder?

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

It's mostly minor complaints. Building a pyd to be put into a package wasn't well documented and it took me a while to figure out to put a dot in the module name parameter like this "tdl.libtcod". Before I attempted to use a slash like a directory, getting bad results as odd parameters were passed to the compiler.

I use setuptools the install my own library in develop mode so I need to be sure that files specific to certain Python versions don't conflict. The build script overwrites the single libtcod.pyd file in CPython but works as I wanted it to in PyPy, so I suspect this is a CPython limitation. And in theory I could make a script that names the file for each version myself. Until then I can just test one version of CPython at a time, so I'm using PyPy 2.7 and CPython 3.4, which covers mostly everything important.

In PyPy 3 older versions of cffi that were in its builtin library were taking priority over the updated versions I installed with pip, I fixed that by reinstalling PyPy 2. Not sure what caused it, could have been all kinds of issues.

So nothing that can't be fixed. The distribution itself is ready, I just have a nagging paranoia that I'm missing something, but I'll go ahead and release what I have so far.

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

Ok, the cffi build has been released. I'm pretty inexperienced with this kind of package distribution so it's probably going to be a rocky start. But if you do manage to get it running it will be much faster than the original library, especially if you get it running in PyPy.

from python-tcod.

techtonik avatar techtonik commented on May 30, 2024

It gives 3.5+ speed up on benchmark. Need to test with updated life. =)

from python-tcod.

HexDecimal avatar HexDecimal commented on May 30, 2024

I guess it's worth summing up my benchmarks so far:
For CPython on CFFI, draw_char is 3x the speed of CPython on ctypes.
For PyPy on CFFI, draw_char is 14x the speed of CPython on ctypes.

from python-tcod.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.