How much is Chipmunk faster then Pymunk?

Official forum for the Chipmunk2D Physics Library.
Post Reply
faiface
Posts: 7
Joined: Sun Feb 24, 2013 2:52 pm
Contact:

How much is Chipmunk faster then Pymunk?

Post by faiface »

Hi!
I'm developing a game in Python 2.7. It'll be 2d parkour game with physically simated stick figure. But I have a problem. I have created classes like Stick, Torso, Head, Joint (but in Slovak language).
Head is of course basic circle.
Torso is made from multiple Sticks.
Stick is made from basic Polygon.
Everything is connected with Joints.
Joint is made from PivotJoint (to connect) and GearJoint (to rotate).
But when I connect everything to make a basic stick figure (generally 1 head, 12 sticks and 11 joints) the FPS is maximum like 60-70, and that's really not enough (when there will be a complete level I can't even imagine how low will it be).
I want to ask if I should write all this as an extension for Python in Cython and use a basic C version of Chipmunk in it. Will it improve FPS enough?
User avatar
slembcke
Site Admin
Posts: 4166
Joined: Tue Aug 14, 2007 7:13 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by slembcke »

Pymunk is just a wrapper of the C code. 99% of the work it does is running as C code. You should be able to run thousands of bodies/joints simultaneously. Pymunk is probably not the problem.
Can't sleep... Chipmunks will eat me...
Check out our latest projects! -> http://howlingmoonsoftware.com/wordpress/
viblo
Posts: 206
Joined: Tue Aug 21, 2007 3:12 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by viblo »

First of all, you should really profile your code to locate the bottleneck(s). Only when you have done that should you start to think about what to do about the problem. When you have located your problem can give you better suggestions about how to improve the performance and if cython would help.

Anyway, in general there are 3 areas where the bottleneck of your performance can be:

1. Somewhere in your code not related to pymunk
In this case it might help with cython in the slow parts. Not to rewrite the pymunk binding, but because python code compiled with cython generally become quicker if tweaked correctly. You can also try other things such as using Pypy instead of cPython. However, the best is usually to first try and improve your code, use better algorithm and so on.

2. In pymunk / the bridge to chipmunk
In this case it will probably help with cython. Ctypes adds a little bit of overhead. Another option you could look into is to wrap with cffi which at least on pypy probably would give you a good speedup while still being a python library.

3. In chipmunk
If the bottleneck is in chipmunk itself it wont help what you do in python land.

Given the information in your post I suspect that the performance problem is not in pymunk nor chipmunk but somewhere else in your code. The platformer demo that is included in pymunk runs in 800 fps on my computer if I turn off the fps restriction.
http://www.pymunk.org - A python library built on top of Chipmunk to let you easily get cool 2d physics in your python game/app
faiface
Posts: 7
Joined: Sun Feb 24, 2013 2:52 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by faiface »

Well, I profiled it but I'm not able to find any bottleneck. As soon as I'm not experienced in profiling, I'm posting the output here. I'd be very happy if you would find anything bad in it.

Code: Select all

Loading chipmunk for Linux (64bit) [/usr/lib/python2.7/site-packages/pymunk/libchipmunk64.so]
Initializing cpSpace - Chipmunk v6.1.1 (Debug Enabled)
Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks
         505656 function calls (505392 primitive calls) in 2.980 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    0.000    0.000 <string>:1(<module>)
        1    0.000    0.000    0.000    0.000 <string>:1(ParseResult)
        1    0.000    0.000    0.000    0.000 <string>:1(SplitResult)
       34    0.000    0.000    0.000    0.000 __init__.py:1045(_get_hashid_private)
        1    0.000    0.000    0.000    0.000 __init__.py:105(__init__)
       13    0.000    0.000    0.000    0.000 __init__.py:1059(_set_collision_type)
       17    0.000    0.000    0.000    0.000 __init__.py:1086(_set_elasticity)
       17    0.000    0.000    0.000    0.000 __init__.py:1096(_set_friction)
     2576    0.003    0.000    0.003    0.000 __init__.py:1138(<lambda>)
        1    0.000    0.000    0.000    0.000 __init__.py:1208(__init__)
      336    0.002    0.000    0.002    0.000 __init__.py:1227(_get_radius)
      112    0.001    0.000    0.001    0.000 __init__.py:1242(_get_offset)
        4    0.000    0.000    0.000    0.000 __init__.py:1254(__init__)
      448    0.003    0.000    0.007    0.000 __init__.py:1273(_get_a)
      448    0.002    0.000    0.006    0.000 __init__.py:1280(_get_b)
      448    0.002    0.000    0.006    0.000 __init__.py:1287(_get_radius)
       12    0.001    0.000    0.001    0.000 __init__.py:1298(__init__)
      112    0.002    0.000    0.003    0.000 __init__.py:134(_get_shapes)
     1344    0.128    0.000    0.615    0.000 __init__.py:1340(get_points)
       13    0.000    0.000    0.000    0.000 __init__.py:1360(moment_for_circle)
       12    0.001    0.000    0.001    0.000 __init__.py:1368(moment_for_poly)
       17    0.000    0.000    0.000    0.000 __init__.py:1434(__init__)
      112    0.001    0.000    0.001    0.000 __init__.py:149(_get_constraints)
        1    0.000    0.000    0.000    0.000 __init__.py:177(_set_gravity)
       26    0.000    0.000    0.001    0.000 __init__.py:266(add)
       17    0.000    0.000    0.000    0.000 __init__.py:316(_add_shape)
       13    0.000    0.000    0.000    0.000 __init__.py:329(_add_body)
       24    0.000    0.000    0.000    0.000 __init__.py:335(_add_constraint)
     1344    0.099    0.000    0.101    0.000 __init__.py:371(step)
        1    0.000    0.000    0.000    0.000 __init__.py:382(add_collision_handler)
        1    0.000    0.000    0.000    0.000 __init__.py:484(_collision_function_helper)
     1372    0.009    0.000    0.009    0.000 __init__.py:496(cast)
        1    0.000    0.000    0.000    0.000 __init__.py:515(_get_cf1)
       17    0.000    0.000    0.000    0.000 __init__.py:516(cf)
       15    0.000    0.000    0.000    0.000 __init__.py:752(__init__)
       12    0.000    0.000    0.000    0.000 __init__.py:783(_set_angle)
    58932    0.083    0.000    0.083    0.000 __init__.py:785(_get_angle)
     1344    0.004    0.000    0.004    0.000 __init__.py:796(_get_rotation_vector)
       17    0.000    0.000    0.000    0.000 __init__.py:806(_set_position)
     7779    0.012    0.000    0.012    0.000 __init__.py:808(_get_position)
        1    0.000    0.000    0.000    0.000 __init__.py:9(<module>)
     1904    0.014    0.000    0.014    0.000 __init__.py:978(_is_static)
        2    0.002    0.001    0.003    0.001 collections.py:237(namedtuple)
       99    0.000    0.000    0.000    0.000 collections.py:277(<genexpr>)
       13    0.000    0.000    0.000    0.000 collections.py:294(<genexpr>)
        1    0.000    0.000    0.000    0.000 compat.py:21(get_BytesIO)
       12    0.000    0.000    0.001    0.000 constraint.py:177(__init__)
     2688    0.004    0.000    0.004    0.000 constraint.py:209(_get_anchr1)
     1344    0.002    0.000    0.002    0.000 constraint.py:215(_get_anchr2)
       12    0.000    0.000    0.000    0.000 constraint.py:422(__init__)
    27613    0.039    0.000    0.039    0.000 constraint.py:434(_get_phase)
        8    0.000    0.000    0.000    0.000 constraint.py:436(_set_phase)
    23053    0.033    0.000    0.033    0.000 constraint.py:59(_get_max_force)
    16140    0.024    0.000    0.024    0.000 constraint.py:61(_set_max_force)
     5376    0.007    0.000    0.007    0.000 constraint.py:90(<lambda>)
     2688    0.004    0.000    0.004    0.000 constraint.py:92(<lambda>)
        1    0.000    0.000    0.000    0.000 dep_util.py:5(<module>)
        1    0.000    0.000    0.000    0.000 errors.py:13(DistutilsError)
        1    0.000    0.000    0.000    0.000 errors.py:16(DistutilsModuleError)
        1    0.000    0.000    0.000    0.000 errors.py:20(DistutilsClassError)
        1    0.000    0.000    0.000    0.000 errors.py:26(DistutilsGetoptError)
        1    0.000    0.000    0.000    0.000 errors.py:29(DistutilsArgError)
        1    0.000    0.000    0.000    0.000 errors.py:33(DistutilsFileError)
        1    0.000    0.000    0.000    0.000 errors.py:38(DistutilsOptionError)
        1    0.000    0.000    0.000    0.000 errors.py:46(DistutilsSetupError)
        1    0.000    0.000    0.000    0.000 errors.py:50(DistutilsPlatformError)
        1    0.000    0.000    0.000    0.000 errors.py:55(DistutilsExecError)
        1    0.000    0.000    0.000    0.000 errors.py:59(DistutilsInternalError)
        1    0.000    0.000    0.000    0.000 errors.py:63(DistutilsTemplateError)
        1    0.000    0.000    0.000    0.000 errors.py:66(DistutilsByteCompileError)
        1    0.000    0.000    0.000    0.000 errors.py:70(CCompilerError)
        1    0.000    0.000    0.000    0.000 errors.py:73(PreprocessError)
        1    0.000    0.000    0.000    0.000 errors.py:76(CompileError)
        1    0.000    0.000    0.000    0.000 errors.py:79(LibError)
        1    0.000    0.000    0.000    0.000 errors.py:83(LinkError)
        1    0.000    0.000    0.000    0.000 errors.py:87(UnknownFileError)
        1    0.001    0.001    0.001    0.001 errors.py:9(<module>)
       17    0.000    0.000    0.001    0.000 figurka.py:102(a)
        8    0.000    0.000    0.001    0.000 figurka.py:107(a)
       13    0.000    0.000    0.000    0.000 figurka.py:112(b_rel)
       12    0.000    0.000    0.001    0.000 figurka.py:116(b)
        8    0.000    0.000    0.001    0.000 figurka.py:121(b)
       12    0.000    0.000    0.001    0.000 figurka.py:126(do_sveta)
        1    0.000    0.000    0.000    0.000 figurka.py:136(__init__)
        1    0.000    0.000    0.000    0.000 figurka.py:171(b_rel)
        1    0.000    0.000    0.000    0.000 figurka.py:175(b)
        1    0.000    0.000    0.000    0.000 figurka.py:180(b)
        1    0.000    0.000    0.000    0.000 figurka.py:185(do_sveta)
       12    0.000    0.000    0.001    0.000 figurka.py:196(__init__)
    16128    0.273    0.000    0.446    0.000 figurka.py:216(aktualizuj)
       13    0.000    0.000    0.000    0.000 figurka.py:23(__init__)
       16    0.000    0.000    0.000    0.000 figurka.py:230(uhol)
        8    0.000    0.000    0.000    0.000 figurka.py:233(uhol)
       12    0.000    0.000    0.001    0.000 figurka.py:252(do_sveta)
        1    0.000    0.000    0.001    0.001 figurka.py:263(__init__)
     1344    0.010    0.000    0.125    0.000 figurka.py:284(aktualizuj)
       11    0.000    0.000    0.000    0.000 figurka.py:290(casti)
        1    0.000    0.000    0.001    0.001 figurka.py:309(a)
        1    0.000    0.000    0.000    0.000 figurka.py:333(do_sveta)
        4    0.000    0.000    0.003    0.001 figurka.py:345(__init__)
     5376    0.031    0.000    0.314    0.000 figurka.py:378(aktualizuj)
        4    0.000    0.000    0.001    0.000 figurka.py:475(do_sveta)
       12    0.000    0.000    0.003    0.000 figurka.py:54(__init__)
       10    0.000    0.000    0.000    0.000 figurka.py:98(a_rel)
       50    0.000    0.000    0.001    0.000 genericpath.py:15(exists)
      130    0.001    0.000    0.003    0.000 genericpath.py:38(isdir)
      114    0.001    0.000    0.001    0.000 genericpath.py:85(_splitext)
        1    0.000    0.000    0.000    0.000 log.py:1(<module>)
        1    0.000    0.000    0.000    0.000 log.py:14(Log)
        1    0.000    0.000    0.000    0.000 log.py:16(__init__)
      114    0.000    0.000    0.003    0.000 pkg_resources.py:1134(safe_name)
      112    0.001    0.000    0.002    0.000 pkg_resources.py:1142(safe_version)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1175(NullProvider)
        2    0.000    0.000    0.000    0.000 pkg_resources.py:1182(__init__)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1195(has_resource)
       49    0.000    0.000    0.002    0.000 pkg_resources.py:1198(has_metadata)
       20    0.000    0.000    0.002    0.000 pkg_resources.py:1202(get_metadata)
       20    0.000    0.000    0.002    0.000 pkg_resources.py:1212(get_metadata_lines)
       71    0.000    0.000    0.001    0.000 pkg_resources.py:1263(_fn)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1278(EggProvider)
        2    0.000    0.000    0.000    0.000 pkg_resources.py:1281(__init__)
        2    0.000    0.000    0.000    0.000 pkg_resources.py:1285(_setup_prefix)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1304(DefaultProvider)
       50    0.000    0.000    0.001    0.000 pkg_resources.py:1307(_has)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1316(get_resource_stream)
       20    0.000    0.000    0.001    0.000 pkg_resources.py:1319(_get)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1337(EmptyProvider)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1345(__init__)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1353(ZipProvider)
        1    0.002    0.002    0.106    0.106 pkg_resources.py:14(<module>)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1521(FileMetadata)
       80    0.000    0.000    0.000    0.000 pkg_resources.py:1533(__init__)
      120    0.000    0.000    0.000    0.000 pkg_resources.py:1536(has_metadata)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1565(PathMetadata)
       34    0.000    0.000    0.000    0.000 pkg_resources.py:1585(__init__)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1590(EggMetadata)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1606(ImpWrapper)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1627(ImpLoader)
        3    0.000    0.000    0.000    0.000 pkg_resources.py:1690(register_finder)
       24    0.000    0.000    0.001    0.000 pkg_resources.py:1700(find_distributions)
        8    0.000    0.000    0.000    0.000 pkg_resources.py:1729(find_nothing)
      130    0.009    0.000    0.037    0.000 pkg_resources.py:1733(find_on_path)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:175(ResolutionError)
        3    0.000    0.000    0.000    0.000 pkg_resources.py:1782(register_namespace_handler)
       33    0.000    0.000    0.007    0.000 pkg_resources.py:1799(_handle_ns)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:180(VersionConflict)
        1    0.000    0.000    0.002    0.002 pkg_resources.py:1820(declare_namespace)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:183(DistributionNotFound)
       57    0.000    0.000    0.006    0.000 pkg_resources.py:1852(fixup_namespace_packages)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:186(UnknownExtra)
       68    0.000    0.000    0.014    0.000 pkg_resources.py:1892(normalize_path)
      757    0.001    0.000    0.004    0.000 pkg_resources.py:1896(_normalize_cached)
       37    0.000    0.000    0.000    0.000 pkg_resources.py:1911(yield_lines)
        3    0.000    0.000    0.000    0.000 pkg_resources.py:197(register_loader_type)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:1992(EntryPoint)
        2    0.000    0.000    0.000    0.000 pkg_resources.py:206(get_provider)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:2120(Distribution)
      114    0.001    0.000    0.007    0.000 pkg_resources.py:2124(__init__)
      114    0.002    0.000    0.011    0.000 pkg_resources.py:2138(from_location)
      399    0.002    0.000    0.003    0.000 pkg_resources.py:2188(key)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:2207(version)
      186    0.001    0.000    0.007    0.000 pkg_resources.py:2251(_get_metadata)
       57    0.001    0.000    0.032    0.001 pkg_resources.py:2256(activate)
      303    0.002    0.000    0.002    0.000 pkg_resources.py:2288(__getattr__)
       57    0.001    0.000    0.022    0.000 pkg_resources.py:2347(insert_on)
        1    0.000    0.000    0.002    0.002 pkg_resources.py:238(get_build_platform)
       57    0.001    0.000    0.017    0.000 pkg_resources.py:2399(check_version_conflict)
        1    0.000    0.000    0.002    0.002 pkg_resources.py:2448(DistInfoDistribution)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:2641(Requirement)
       26    0.001    0.000    0.001    0.000 pkg_resources.py:2741(_get_mro)
       16    0.000    0.000    0.000    0.000 pkg_resources.py:2744(cls)
       26    0.000    0.000    0.001    0.000 pkg_resources.py:2748(_find_adapter)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:2798(_initialize)
       57    0.000    0.000    0.032    0.001 pkg_resources.py:2835(<lambda>)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:348(IMetadataProvider)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:380(IResourceProvider)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:421(WorkingSet)
        1    0.000    0.000    0.026    0.026 pkg_resources.py:424(__init__)
       24    0.001    0.000    0.044    0.002 pkg_resources.py:438(add_entry)
       58    0.000    0.000    0.000    0.000 pkg_resources.py:503(__iter__)
      114    0.002    0.000    0.005    0.000 pkg_resources.py:520(add)
        4    0.000    0.000    0.000    0.000 pkg_resources.py:57(_declare_state)
        1    0.000    0.000    0.033    0.033 pkg_resources.py:698(subscribe)
       57    0.000    0.000    0.000    0.000 pkg_resources.py:707(_added_new)
        1    0.000    0.000    0.002    0.002 pkg_resources.py:724(Environment)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:870(ExtractionError)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:888(ResourceManager)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:892(__init__)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:895(resource_exists)
        1    0.000    0.000    0.000    0.000 pkg_resources.py:911(resource_stream)
        1    0.000    0.000    0.002    0.002 pkg_resources.py:93(get_supported_platform)
        1    0.002    0.002    0.108    0.108 pkgdata.py:18(<module>)
        1    0.000    0.000    0.000    0.000 pkgdata.py:34(getResource)
        1    0.000    0.000    0.000    0.000 pkgutil.py:1(<module>)
        1    0.000    0.000    0.000    0.000 pkgutil.py:162(ImpImporter)
       45    0.000    0.000    0.000    0.000 pkgutil.py:173(__init__)
       29    0.000    0.000    0.007    0.000 pkgutil.py:176(find_module)
        1    0.000    0.000    0.000    0.000 pkgutil.py:232(ImpLoader)
        1    0.000    0.000    0.000    0.000 pkgutil.py:31(simplegeneric)
       57    0.000    0.000    0.000    0.000 pkgutil.py:366(get_importer)
        1    0.000    0.000    0.000    0.000 pkgutil.py:59(register)
       59    0.000    0.000    0.001    0.000 posixpath.py:118(dirname)
      389    0.002    0.000    0.006    0.000 posixpath.py:130(islink)
       97    0.002    0.000    0.003    0.000 posixpath.py:312(normpath)
       97    0.000    0.000    0.004    0.000 posixpath.py:341(abspath)
       97    0.003    0.000    0.019    0.000 posixpath.py:355(realpath)
       68    0.000    0.000    0.000    0.000 posixpath.py:43(normcase)
      194    0.001    0.000    0.001    0.000 posixpath.py:51(isabs)
      574    0.005    0.000    0.008    0.000 posixpath.py:60(join)
       12    0.000    0.000    0.000    0.000 posixpath.py:80(split)
      114    0.000    0.000    0.001    0.000 posixpath.py:95(splitext)
     1344    0.040    0.000    0.801    0.001 pygame_util.py:127(draw_poly)
      448    0.018    0.000    0.084    0.000 pygame_util.py:149(draw_segment)
     2688    0.074    0.000    0.247    0.000 pygame_util.py:175(draw_constraint)
    17248    0.119    0.000    0.182    0.000 pygame_util.py:223(to_pygame)
      112    0.020    0.000    1.218    0.011 pygame_util.py:45(draw_space)
     1904    0.015    0.000    0.929    0.000 pygame_util.py:81(draw_shape)
      112    0.006    0.000    0.021    0.000 pygame_util.py:99(draw_circle)
      226    0.001    0.000    0.004    0.000 re.py:144(sub)
       13    0.000    0.000    0.017    0.001 re.py:188(compile)
      239    0.001    0.000    0.019    0.000 re.py:226(_compile)
        1    0.000    0.000    0.000    0.000 spawn.py:7(<module>)
       28    0.000    0.000    0.001    0.000 sre_compile.py:178(_compile_charset)
       28    0.001    0.000    0.001    0.000 sre_compile.py:207(_optimize_charset)
       27    0.000    0.000    0.000    0.000 sre_compile.py:24(_identityfunction)
        1    0.000    0.000    0.000    0.000 sre_compile.py:258(_mk_bitmap)
    92/14    0.002    0.000    0.005    0.000 sre_compile.py:32(_compile)
       40    0.000    0.000    0.000    0.000 sre_compile.py:354(_simple)
       14    0.000    0.000    0.002    0.000 sre_compile.py:361(_compile_info)
       28    0.000    0.000    0.000    0.000 sre_compile.py:474(isstring)
       14    0.000    0.000    0.007    0.001 sre_compile.py:480(_code)
       14    0.000    0.000    0.018    0.001 sre_compile.py:495(compile)
      179    0.000    0.000    0.001    0.000 sre_parse.py:126(__len__)
      343    0.001    0.000    0.002    0.000 sre_parse.py:130(__getitem__)
       40    0.000    0.000    0.000    0.000 sre_parse.py:134(__setitem__)
      111    0.000    0.000    0.001    0.000 sre_parse.py:138(append)
   132/54    0.001    0.000    0.001    0.000 sre_parse.py:140(getwidth)
       14    0.000    0.000    0.000    0.000 sre_parse.py:178(__init__)
      303    0.001    0.000    0.002    0.000 sre_parse.py:182(__next)
      199    0.000    0.000    0.001    0.000 sre_parse.py:195(match)
      234    0.001    0.000    0.002    0.000 sre_parse.py:201(get)
       16    0.000    0.000    0.000    0.000 sre_parse.py:210(isident)
        4    0.000    0.000    0.000    0.000 sre_parse.py:216(isname)
        2    0.000    0.000    0.000    0.000 sre_parse.py:225(_class_escape)
       30    0.000    0.000    0.000    0.000 sre_parse.py:257(_escape)
    40/14    0.001    0.000    0.009    0.001 sre_parse.py:301(_parse_sub)
    48/14    0.003    0.000    0.009    0.001 sre_parse.py:379(_parse)
       14    0.000    0.000    0.010    0.001 sre_parse.py:663(parse)
       14    0.000    0.000    0.000    0.000 sre_parse.py:67(__init__)
       26    0.000    0.000    0.000    0.000 sre_parse.py:72(opengroup)
       26    0.000    0.000    0.000    0.000 sre_parse.py:83(closegroup)
       92    0.000    0.000    0.000    0.000 sre_parse.py:90(__init__)
      516    0.001    0.000    0.001    0.000 stat.py:24(S_IFMT)
      130    0.000    0.000    0.001    0.000 stat.py:40(S_ISDIR)
      386    0.001    0.000    0.002    0.000 stat.py:55(S_ISLNK)
        1    0.000    0.000    0.000    0.000 string.py:220(lower)
        3    0.000    0.000    0.000    0.000 string.py:511(replace)
        1    0.043    0.043    2.980    2.980 sutikman.py:24(main)
       17    0.000    0.000    0.000    0.000 sutikman.py:34(<lambda>)
        1    0.000    0.000    0.000    0.000 urlparse.py:113(SplitResult)
        1    0.000    0.000    0.000    0.000 urlparse.py:121(ParseResult)
        1    0.001    0.001    0.008    0.008 urlparse.py:29(<module>)
      485    0.002    0.000    0.003    0.000 urlparse.py:315(<genexpr>)
        1    0.000    0.000    0.000    0.000 urlparse.py:68(ResultMixin)
        1    0.000    0.000    0.000    0.000 util.py:16(get_platform)
        1    0.001    0.001    0.002    0.002 util.py:5(<module>)
       12    0.000    0.000    0.000    0.000 util.py:52(is_clockwise)
    10760    0.026    0.000    0.057    0.000 vec2d.py:105(__ne__)
    25365    0.148    0.000    0.255    0.000 vec2d.py:147(__add__)
       19    0.000    0.000    0.000    0.000 vec2d.py:169(__sub__)
     3730    0.029    0.000    0.050    0.000 vec2d.py:324(rotated)
    10752    0.051    0.000    0.072    0.000 vec2d.py:479(cpvrotate)
       70    0.000    0.000    0.000    0.000 vec2d.py:61(from_param)
    50895    0.165    0.000    0.253    0.000 vec2d.py:66(__init__)
    56016    0.076    0.000    0.076    0.000 vec2d.py:78(__getitem__)
     1372    0.002    0.000    0.002    0.000 {_ctypes.POINTER}
       14    0.000    0.000    0.000    0.000 {_sre.compile}
        8    0.000    0.000    0.000    0.000 {_sre.getlower}
       13    0.000    0.000    0.000    0.000 {_weakref.proxy}
       24    0.000    0.000    0.000    0.000 {abs}
       13    0.000    0.000    0.000    0.000 {all}
       56    0.000    0.000    0.002    0.000 {built-in method fromkeys}
      484    0.001    0.000    0.001    0.000 {chr}
        1    0.000    0.000    0.000    0.000 {dir}
      234    0.000    0.000    0.000    0.000 {getattr}
        5    0.000    0.000    0.000    0.000 {globals}
    29357    0.074    0.000    0.076    0.000 {hasattr}
       58    0.000    0.000    0.000    0.000 {imp.acquire_lock}
       29    0.001    0.000    0.001    0.000 {imp.find_module}
       58    0.000    0.000    0.000    0.000 {imp.release_lock}
    39139    0.058    0.000    0.058    0.000 {isinstance}
2829/2781    0.004    0.000    0.005    0.000 {len}
        2    0.000    0.000    0.000    0.000 {locals}
      117    0.001    0.000    0.025    0.000 {map}
     3730    0.006    0.000    0.006    0.000 {math.cos}
     3730    0.005    0.000    0.005    0.000 {math.sin}
      460    0.001    0.000    0.001    0.000 {max}
       13    0.000    0.000    0.000    0.000 {method '__contains__' of 'frozenset' objects}
       48    0.000    0.000    0.000    0.000 {method 'add' of 'set' objects}
    12168    0.014    0.000    0.014    0.000 {method 'append' of 'list' objects}
       20    0.000    0.000    0.000    0.000 {method 'close' of 'file' objects}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}
     4938    0.006    0.000    0.006    0.000 {method 'endswith' of 'str' objects}
        5    0.000    0.000    0.000    0.000 {method 'extend' of 'list' objects}
      112    0.110    0.001    0.110    0.001 {method 'fill' of 'pygame.Surface' objects}
        4    0.000    0.000    0.000    0.000 {method 'find_module' of 'imp.NullImporter' objects}
      344    0.001    0.000    0.001    0.000 {method 'get' of 'dict' objects}
      112    0.000    0.000    0.000    0.000 {method 'get_fps' of 'Clock' objects}
    17248    0.018    0.000    0.018    0.000 {method 'get_height' of 'pygame.Surface' objects}
      112    0.001    0.000    0.001    0.000 {method 'get_size' of 'pygame.Surface' objects}
      114    0.000    0.000    0.000    0.000 {method 'group' of '_sre.SRE_Match' objects}
       57    0.000    0.000    0.000    0.000 {method 'index' of 'list' objects}
       86    0.000    0.000    0.000    0.000 {method 'isalnum' of 'str' objects}
       13    0.000    0.000    0.000    0.000 {method 'isdigit' of 'str' objects}
     1358    0.002    0.000    0.002    0.000 {method 'items' of 'dict' objects}
        4    0.000    0.000    0.000    0.000 {method 'iteritems' of 'dict' objects}
       99    0.000    0.000    0.000    0.000 {method 'join' of 'str' objects}
     2301    0.004    0.000    0.004    0.000 {method 'lower' of 'str' objects}
      115    0.001    0.000    0.001    0.000 {method 'match' of '_sre.SRE_Pattern' objects}
       20    0.000    0.000    0.000    0.000 {method 'read' of 'file' objects}
       26    0.000    0.000    0.000    0.000 {method 'remove' of 'list' objects}
      119    0.000    0.000    0.000    0.000 {method 'replace' of 'str' objects}
      299    0.001    0.000    0.001    0.000 {method 'rfind' of 'str' objects}
       67    0.000    0.000    0.000    0.000 {method 'rstrip' of 'str' objects}
      254    0.000    0.000    0.000    0.000 {method 'setdefault' of 'dict' objects}
      296    0.001    0.000    0.001    0.000 {method 'split' of 'str' objects}
       20    0.000    0.000    0.000    0.000 {method 'splitlines' of 'str' objects}
     1899    0.003    0.000    0.003    0.000 {method 'startswith' of 'str' objects}
       21    0.000    0.000    0.000    0.000 {method 'strip' of 'str' objects}
      226    0.001    0.000    0.001    0.000 {method 'sub' of '_sre.SRE_Pattern' objects}
      112    0.010    0.000    0.010    0.000 {method 'tick' of 'Clock' objects}
      112    0.001    0.000    0.001    0.000 {method 'values' of 'dict' objects}
      196    0.000    0.000    0.000    0.000 {min}
       21    0.000    0.000    0.000    0.000 {open}
       60    0.000    0.000    0.000    0.000 {ord}
       16    0.000    0.000    0.000    0.000 {posix.access}
       16    0.002    0.000    0.002    0.000 {posix.listdir}
      389    0.002    0.000    0.002    0.000 {posix.lstat}
      180    0.002    0.000    0.002    0.000 {posix.stat}
        1    0.000    0.000    0.000    0.000 {posix.uname}
      112    0.456    0.004    0.456    0.004 {pygame.display.flip}
      113    0.412    0.004    0.412    0.004 {pygame.display.set_caption}
        1    0.019    0.019    0.128    0.128 {pygame.display.set_mode}
     1344    0.006    0.000    0.006    0.000 {pygame.draw.aalines}
     2800    0.012    0.000    0.012    0.000 {pygame.draw.circle}
     1904    0.025    0.000    0.025    0.000 {pygame.draw.lines}
      113    0.003    0.000    0.003    0.000 {pygame.event.get}
        1    0.000    0.000    0.000    0.000 {pygame.time.Clock}
     1582    0.004    0.000    0.004    0.000 {range}
        2    0.000    0.000    0.000    0.000 {repr}
        2    0.000    0.000    0.000    0.000 {sys._getframe}
       12    0.000    0.000    0.000    0.000 {zip}

And well, you must have a pretty powerful computer because to me, platformer demo is with maximum FPS set to 1000 running just at 150 :).
viblo
Posts: 206
Joined: Tue Aug 21, 2007 3:12 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by viblo »

Interesting about your max fps.. I tested on my stationary which is almost 3 years old, but contains gaming stuff. Now I reran it on my other computer, a laptop about 2 years old similar to a macbook air in performance and got around 200. Much bigger difference than I thought I would get for this type of test.

To investigate a profile I usually sort it by cumtime and tottime and then look at the top 5-10 entries depending on how much each entry contribute.

If we sort by tottime (which is time spent in a function excluding calls to sub functions), you will find that the top entries are display.flip() and display.set_caption() with 0.4 sec each. flip we cant do anything about, we need to flip the screen. But you could rewrite the code to not update the caption every frame, should be enough once every second :)

If we instead sort by cumtime (time spent in a function including calls to sub functions), you will find that most time is spent in your main method. This is of course nothing strange. Next entry is the draw_space method, a whole 1.2 seconds is spent in there. The pymunk pygame drawing methods are really not that optimized and is mostly intended for debugging and prototyping easily. They redraw everything each frame, that is not the best way to draw with pygame (but the easiest).

With this info I suggest you try and run without drawing to get an estimate on how much time is spent drawing (for example, add a button to toggle drawing). When you have an estimate maybe you should investigate how to optimize the drawing part of the code. Either implement your own drawing in pygame, or use something else like pyglet instead.

I also have two small suggestions on profiling:
Its usually a good idea to sort the output to have it easier to read. Otherwise you more or less have to paste it into something else for sorting (I copied your output to excel). I often use the sorting found in balls_and_lines.py demo, but it is usually a good idea to sort it in other ways as well to find the easiest to improve spots.

I also like to run the program for a little bit longer, like 20-30 sec. Usually I run quicker iterations for just a few seconds like in your case, and then longer runs to easier make sure startup and loading code doesnt show up in the profile.

Edit: I tested to remove the call to draw_space in the platformer demo and the fps on both my computers doubled..
http://www.pymunk.org - A python library built on top of Chipmunk to let you easily get cool 2d physics in your python game/app
faiface
Posts: 7
Joined: Sun Feb 24, 2013 2:52 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by faiface »

Alright, so I just tried to run without drawing.
When I just removed draw_space, fps got higher by 30-40%. When I removed all drawing including pygame.display.flip(), and just printed fps, I got around 200 which is almost 4x more than with all drawing.
I also tried to do the same with platformer and I got around 1000 FPS, so my game is 5x slower.
But I really cannot find out what's wrong with my code.
One "maybe solution" would be to switch to pyglet.
Or should I send you my code?
viblo
Posts: 206
Joined: Tue Aug 21, 2007 3:12 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by viblo »

My experience is that to have quick drawing in pygame you need to not redraw so much of the screen each frame, each pixel draw costs a little bit, a 2x2 square is much less expensive to draw than a 100x100 square. Using OpenGL (for example with pyglet) its more or less free to draw a pixel meaning a 2x2 square is as expensive as a 100x100 square. However, each draw call is expensive, meaning its more expensive to draw 50x100 twice than 100x100 once.

This also means that pygame is much more sensitive to the resolution (drawing 1920x1200 pixels is much much more expensive than 640x480 for example).

Another thing to remember is that pyglet/OpenGL drawing depends in a large way on your graphics card while pygame uses mostly cpu power for drawing. So a computer with a slow graphics card (such as lightweight laptops and old computers with no external card) will probably be better at pygame than pyglet.

But I dont have so much experience with optimizing pygame drawing. I usually use it for small experiments/prototypes because its easy and very widespread, but in the last couple of full games (where performance matters) I used pyglet. Maybe you could try and post to the pygame mailing list? (and/or do an experiment with pyglet)
http://www.pymunk.org - A python library built on top of Chipmunk to let you easily get cool 2d physics in your python game/app
faiface
Posts: 7
Joined: Sun Feb 24, 2013 2:52 pm
Contact:

Re: How much is Chipmunk faster then Pymunk?

Post by faiface »

I've just rewritten that to Pyglet and the performance increased very much. Thank you for your time helping me :). I really don't know why is PyGame so slow on my computer, but Pyglet is just ok so I will continue my game development with it.
Post Reply

Who is online

Users browsing this forum: No registered users and 16 guests