[pypy-issue] [issue909] My code is slower under PyPy than under cPython

Michal tracker at bugs.pypy.org
Sat Oct 15 21:37:50 CEST 2011


New submission from Michal <mmierzwa at tycowaterworks.pl>:

I tried to run my code under different python implementations:
under pypy is slower then cpython, under psyco it is much slower first time I 
invoke it and then it is much quicker, compiled with cython is slightly faster.
Please see privided example. Just run and it returns ms spent on it.
In my machine (pypy ver: 
Python 2.7.1 (080f42d5c4b4, Aug 23 2011, 11:41:11)
[PyPy 1.6.0 with MSC v.1500 32 bit] on win32 )
cpython: about 8 ms
pypy: about 18 ms

----------
files: main.py
messages: 3305
nosy: mmierzwa, pypy-issue
priority: wish
status: unread
title: My code is slower under PyPy than under cPython

________________________________________
PyPy bug tracker <tracker at bugs.pypy.org>
<https://bugs.pypy.org/issue909>
________________________________________
-------------- next part --------------
'''
Created on 15-10-2011

@author: root
'''

from time import clock, time

class SW(object):
    """
    It is used to measure time intervals
    """
    
    #file handler common to all objects of this class
    log = None
     
    def __init__(self, name):
        #defines target where logs will be stored to
        self.log_to = {"console": True}   
        self.timer = 0;
        self.name = name
        self.alltimer = 0
        self.allclock = 0
        self.pause_all_timer = 0
        self.pause_all_clock = 0
        self.pause_timer = 0
        self.pause_clock = 0
        
        
    def start(self):
        if self.log_to["console"]:
            print "SW started for: " + self.name        
        self.timer = time()
        self.clock = clock()
        
        
    def pause(self):
        self.pause_timer = time()
        self.pause_clock = clock()
        
        
    def resume(self):
        self.pause_all_timer += time() - self.pause_timer
        self.pause_timer = 0
        self.pause_all_clock += clock() - self.pause_clock
        self.pause_clock = 0  
        
        
    def stop(self):
        if self.pause_timer != 0: self.resume()
        self.alltimer = time() - self.timer - self.pause_all_timer
        self.allclock = clock() - self.clock - self.pause_all_clock
        if self.log_to["console"]:
            print self.name + " has taken: " + str(round(self.alltimer * 1000)) + "ms, busy: " + str(round(self.allclock *1000)) + "ms."
        return round(self.alltimer * 1000), round(self.allclock *1000)


def get_point_content1(_, _1, _2, _3):
    return []


ALT_COLORS = ( (-20, "^4", "^b"),            #deep water 
               (00, "^6", "^c"),           #shallow water
               (20, "^2", "^g"), 
               (40, "^3", "^y"),
               (60, "^1", "^r"), 
               (80, "^5", "^m") )

def get_alt_color1(alt):
    if alt < ALT_COLORS[0][0]: return ALT_COLORS[0][1]
    if alt < ALT_COLORS[1][0]: return ALT_COLORS[1][1]
    if alt < ALT_COLORS[2][0]: return ALT_COLORS[2][1]
    if alt < ALT_COLORS[3][0]: return ALT_COLORS[3][1]
    if alt < ALT_COLORS[4][0]: return ALT_COLORS[4][1]
    if alt < ALT_COLORS[5][0]: return ALT_COLORS[5][1]
    return ALT_COLORS[5][1]


def get_alt1(x, y, area):
    return 0


#Kinds of items
ALL = 0
PCS = 1
OBJECTS = 2    
WORMHOLE = 3
MOBS = 4
DESC = 5  
PARAMS = 6
ALT = 7  

COLORS1 = { 'DIR': "^g", OBJECTS: "^w", MOBS: "^m", WORMHOLE: "^y", DESC: "^W"}  
MAP_COLORS1 = { ALL: "^W", OBJECTS: "^W", MOBS: "^M", WORMHOLE: "^Y"}  


def size_dist_rel1(size,dist, sight):
    return dist < size / 3 + sight


def get_heights_area(aname):
    return {}    


def get_area(aname):
    return {}


BLOCK_VOLATILE = 0 #in ex. parameters, description
BLOCK_NONE = 1 #in example knife
BLOCK_BLOCKING = 2 #usually mobs
BLOCK_ALL = 3 #usually walls
blocking_rules = {BLOCK_VOLATILE: [False,False,False,False],
                  BLOCK_NONE: [False,False,False,True],
                  BLOCK_BLOCKING: [False,False,True,True],
                  BLOCK_ALL: [False,True,True,True]}   


def get_lang(what, _):
    return what


def eval_dir_dist(nx,ny,dist,srange):
    "Evaluate direction and distance of point"
    wsp = abs(float(ny) / (nx - 0.001))
    _lang = 'pl'
    if wsp >= 2:
        if ny > 0:
            dir2 = "N  "
        else:
            if ny < 0:
                dir2 = "S  "
    else:
        if wsp > 0.5:
            if ny > 0 and nx > 0:
                dir2 = "NE "
            else:
                if ny > 0 and nx < 0:
                    dir2 = "NW "
                else:
                    if ny < 0 and nx > 0:
                        dir2 = "SE "
                    else:
                        if ny < 0 and nx < 0:
                            dir2 = "SW "
        else:
            if wsp <= 0.5:
                if nx > 0:
                    dir2 = "E  "
                else:
                    if nx < 0:
                        dir2 = "W  "    
    if dist < 3:
        dir3 = get_lang('close', _lang) + "\t"
    else:
        if dist < 5:
            dir3 = get_lang('farther', _lang) + "\t"
        else:
            dir3 = get_lang('far', _lang) + "\t"
    return dir2, dir3


def create_next_sign(nb):
    "Creates next sign to display on the map view"
    if nb < 10:
        sc = chr(nb + ord('0')) 
    else:
        if nb < 36:
            sc = chr(nb - 10 + ord('A'))
        else:
            if nb < 62:
                sc = chr(nb - 36 + ord('a'))
            else: 
                sc = '*'
    return sc  


def NL():
    return


def rsendNL(what):
    print what
    
    
def get_alt(x,y, aname):
    "Returns ground altitude of that point"
    #@inlined in mud.pathfinding.cached_passable - UPDATE IT THERE
    area = get_heights_area(aname)
    return 0


def get_neighbouring_point(x, y, area):
    "Returns mobs in point x,y"
    mylist = []
    mylang = 'pl'
    content = get_point_content1(x, y, area, MOBS)
    for itm in content:
        if itm.myname:
            mylist.append(itm.name[mylang].name + ": " + itm.myname.name + " [" + str(itm.get_id_short()) + "]^~")
        else:
            mylist.append(itm.name[mylang].name + " [" + str(itm.get_id_short()) + "]^~")
    return ", ".join(mylist)


def show_neighbourhood():
    "Shows mobs in naighbouring points"
    mx = 0
    my = 0
    aname = 'space'
    altarea = get_heights_area(aname)
    area = get_area(aname)
    _get_alt_color = get_alt_color1
    _get_alt = get_alt1
    _gnp = get_neighbouring_point
    _s = rsendNL

    alt = _get_alt(mx-1, my+1, altarea)
    content = _gnp(mx-1, my+1, area)
    if content:
        _s(_get_alt_color(alt) + "NW:^~\t" + content)

    alt = _get_alt(mx, my+1, altarea)
    content = _gnp(mx, my+1, area)
    if content:
        _s(_get_alt_color(alt) + "N:^~\t" + content)

    alt = _get_alt(mx+1, my+1, altarea)
    content = _gnp(mx+1, my+1, area)
    if content:
        _s(_get_alt_color(alt) + "NE:^~\t" + content)

    alt = _get_alt(mx-1, my, altarea)
    content = _gnp(mx-1, my, area)
    if content:
        _s(_get_alt_color(alt) + "W:^~\t" + content)

    alt = _get_alt(mx+1, my, altarea)
    content = _gnp(mx+1, my, area)
    if content:
        _s(_get_alt_color(alt) + "E:^~\t" + content)

    alt = _get_alt(mx-1, my-1, altarea)
    content = _gnp(mx-1, my-1, area)
    if content:
        _s(_get_alt_color(alt) + "SW:^~\t" + content)

    alt = _get_alt(mx, my-1, altarea)
    content = _gnp(mx, my-1, area)
    if content:
        _s(_get_alt_color(alt) + "S:^~\t" + content)

    alt = _get_alt(mx+1, my-1, altarea)
    content = _gnp(mx+1, my-1, area)
    if content:
        _s(_get_alt_color(alt) + "SE:^~\t" + content)
    
    
def show_here(prm = None):
    "Display content of point we are standing in and neighbouring mobs"
    NL()
    _DESC = DESC
    _OBJECTS = OBJECTS
    _WORMHOLE = WORMHOLE
    _COLORS = COLORS1
    _get_point_content = get_point_content1
    mylang = 'pl'
    aname = 'space'
    area = get_area(aname)
    mx = 0
    my = 0
    my_point_alt = get_alt(mx, my, aname)
    rsendNL( get_alt_color1(my_point_alt) + 'here' + "^~")
    itms = _get_point_content(mx, my, area, _DESC)
    if itms: found_descs = []
    count = 0
    for itm in itms: 
        itm_name = itm.name[mylang].name
        if itm.desc:
            found_descs.append(itm)
            count += 1
            rsendNL(_COLORS[_DESC] + itm_name + "[" + str(count) + "]^~")
        else:
            rsendNL(_COLORS[_DESC] + itm_name + "^~")
    buf = {}
    itms = _get_point_content(mx, my, area, _OBJECTS)
    for itm in itms:
        itm_name = itm.name[mylang].name
        if itm_name in buf: 
            buf[itm_name].append(itm.get_id_short())
        else:
            buf[itm_name] = [itm.get_id_short()]
    strbuff = ""
    for name in buf:
        if strbuff != "": strbuff += ", " 
        if len(buf[name]) > 1:
            strbuff += "(" + str(len(buf[name])) + ") " + name + " " + str(buf[name])
        else:
            strbuff += name + " " + str(buf[name])
    if strbuff: rsendNL(_COLORS[_OBJECTS] + strbuff + "^~")
    itms = _get_point_content(mx, my, area, _WORMHOLE)
    for itm in itms:
        itm_name = itm.name[mylang].name
        rsendNL(_COLORS[_WORMHOLE] + itm_name + " [" + str(itm.get_id_short()) + "]^~")       
    NL() 
    show_neighbourhood()
    rsendNL("A: " + aname + "\tX: " + str(mx) + "\tY: " + str(my) + "\tZ: " + str(my_point_alt))
    
    
def sight_range():
    "Return sight range, that is how big map it can see"
    return 8


def get_sight():
    "Returns sight ability of a mob, normal is 0"
    return 0;


def map_directions():
    "Displays map and directions and distances of items (look 1)"
    sw = SW("Look map directions")
    sw.start()      
    #shorthands
    get_point_content = get_point_content1
    get_alt_color = get_alt_color1
    get_alt = get_alt1
    MAP_COLORS = MAP_COLORS1
    COLORS = COLORS1
    size_dist_rel = size_dist_rel1
    _abs = abs
    aname = 'space'
    altarea = get_heights_area(aname)
    area = get_area(aname)
    srange = sight_range()
    mx = 0
    my = 0
    my_ground_alt = get_alt(mx, my, altarea)
    height = 0
    m_alt = my_ground_alt + height
    NL()             
    lang = 'pl'
               
    lmap = {}
    #counter of unique signs on map
    nb = 0
    #containter of the legend to map
    legend = []
    #iterate over the perimeter
    for ii in xrange(-srange, srange+1): 
        for side in ((ii,srange), (ii,-srange), (srange,ii), (-srange,ii)):
            nx = side[0]
            ny = side[1]
            #calculate line from 0,0 to nx,ny point
            if _abs(ny) > _abs(nx):
                dist = ny
            else:
                dist = nx
            w = ny/(nx + 0.01)
            if dist >= 0:
                di = 1
            else:
                di = -1
            a = -999
            #iterate over points lying on that line
            for i in xrange(di, dist+di, di):
                if _abs(nx) >= _abs(ny):
                    ax = i
                    ay = round(ax * (w + 0.01))
                else:
                    ay = i
                    ax = round(ay / (w + 0.01))
                if (ax,ay) in lmap:
                    if 'a' in lmap[(ax,ay)]:
                        a = lmap[(ax,ay)]['a']
                    continue
                #altitude of that point
                b_alt = g_alt = get_alt(ax+mx, ay+my, altarea)
                cellcolor = get_alt_color(b_alt)                    
                #fetch all cell items
                #@inline itms = get_point_content(ax+mx, ay+my, area, world.ALL)
                x_gpc, y_gpc = ax+mx, ay+my
                itms = []
                if (x_gpc,y_gpc) in area: 
                    point = area[(x_gpc,y_gpc)]
                    itms.extend(point[MOBS].values())
                    itms.extend(point[OBJECTS].values())
                    if WORMHOLE in point: itms.extend(point[WORMHOLE].values())
                #@inline end itms = get_point_content(ax+mx, ay+my, area, world.ALL)
                if itms:
                    for itm in itms:
                        if itm.blocking == BLOCK_ALL:
                            b_alt += itm.height
                lmap[(ax,ay)] = {}
                map_cell = lmap[(ax,ay)]                    
                fc = cellcolor + " "
                sc = " "
                #check whether point lies above line of sight
                min_visible_height = a * _abs(i) + m_alt
                if b_alt > min_visible_height:
                    #calculate new line 'a' parameter between 0,0 and that point
                    a = (b_alt - m_alt)/float(_abs(i))
                    lmap[(ax,ay)]['a'] = a
                if b_alt > min_visible_height:
                    covered = False
                else:
                    #this cell lies under the line of sight 
                    fc = cellcolor + "^K."
                    covered = True
                if not itms:
                    lmap[(ax,ay)]['cell'] = fc + sc
                    continue
                #list of items in that point
                cell_items = {}
                #most important kind of items in that point
                most_important_kind = 0
                for itm in itms:
                    #if item too small it will not be visible, depends also of how good sight mob has
                    if not size_dist_rel(itm.size, _abs(i), get_sight()):
                        continue
                    #if point not visible check if item is height enough to be visible if not, we can omit it
                    if covered:
                        if itm.blocking != BLOCK_ALL and g_alt + itm.height < min_visible_height: continue
                    #if itm has it's own fixed sign or even both signs 
                    if itm.on_map == itm.MAP_FIXED:
                        #we can set it's color
                        if covered:
                            fc = "^K" + itm.std_char1
                        else:
                            fc = MAP_COLORS[OBJECTS] + itm.std_char1
                        #and if it has second char and it is not occupied we can display it either
                        if sc == " " and itm.std_char2:
                            sc = itm.std_char2
                        continue
                    #we want to know what most important item type is in cell in order to know how to color it      
                    if itm.kind > most_important_kind:
                        most_important_kind = itm.kind    
                    #if list of items is empty we have to prepare it
                    if not cell_items:
                        #obtain direction and distance name
                        dirg, distg = eval_dir_dist(ax,ay,_abs(i),srange)
                        #we do not have sign for this cell yet
                        sc = create_next_sign(nb)
                        nb += 1
                        direction = sc + ". " + COLORS['DIR'] + "[" + dirg + distg + "]^~ "
                    itm_name = itm.name[lang].name
                    #if itm is not in list
                    if itm_name not in cell_items:
                        #we have to add it
                        cell_items[itm_name] = [1,itm.kind, [itm.get_id_short()]]
                    else:
                        #otherwise just increase its counter
                        cell_items[itm_name][0] += 1
                        cell_items[itm_name][2].append(itm.get_id_short())                            
                if covered:
                    map_cell['cell'] = cellcolor + fc + "^K" + sc
                else:
                    map_cell['cell'] = cellcolor + fc + MAP_COLORS[most_important_kind] + sc    
                str_items = ""
                first_elm = True
                for elm in cell_items:
                    if not first_elm: 
                        str_items += ", "
                    else:
                        first_elm = False
                    str_items += COLORS[cell_items[elm][1]]
                    if cell_items[elm][0] > 1:
                        str_items += "(" + str(cell_items[elm][0]) + ") "
                    str_items += elm + " " + str(cell_items[elm][2]) + "^~"
                if str_items: legend.append(direction + str_items)
                                
    #display map
    for y in xrange(srange, -srange-1, -1):
        row = "  "
        for x in xrange(-srange, srange + 1):  
            if x == 0 and y == 0:
                content = get_point_content(mx, my, area, OBJECTS)
                fc = " "
                for itm in content:
                    if itm.on_map == itm.MAP_FIXED:
                        fc = MAP_COLORS[OBJECTS] + itm.std_char1
                        break
                row += get_alt_color(my_ground_alt) + fc + "^G@"
                continue
            row += lmap[(x,y)]['cell']
        rsendNL(row + "^~")
    #display legend
    NL()
    for elm in legend:
        rsendNL(elm)
    show_here()
    sw.stop()


if __name__ == '__main__':
    map_directions()
    pass


More information about the pypy-issue mailing list