GAE有各种各样的限制,其中一个是最大可分配内存块的大小达1Mb(现在是10倍,但这不会改变问题).限制意味着不能在list()中放置更多的项目,因为CPython会尝试为元素指针分配连续的内存块.拥有巨大的list()可以被认为是糟糕的编程习惯,但即使程序本身没有创建庞大的结构,CPython也会在后台维护一些.
似乎CPython正在维护单个全局对象列表或其他东西.即具有许多小对象的应用程序倾向于分配越来越大的单个内存块.
第一个想法是gc,禁用它会稍微改变应用程序行为,但仍然会保留一些结构.
遇到问题的最简单的简短应用程序是:
a = b = []
number_of_lists = 8000000
for i in xrange(number_of_lists):
b.append([])
b = b[0]
Run Code Online (Sandbox Code Playgroud)
任何人都可以告诉我如何防止CPython在应用程序中有很多对象时分配巨大的内部结构?
为我的CPython扩展类型实现!=和==,我应该实现tp_compare,tp_richcompare还是两者兼而有之?
在什么情况下他们都被称为?
我搜索了一段时间,发现了一些合理的说法,即 CPython 的编译允许更快地执行 Python 代码。不过,我想知道是否有人知道任何可以证明加速程度的基准测试。
或者,也许有一种简单的方法可以让我对其进行基准测试。是否有一个可以在运行时给出的Python标志来关闭编译?
我想@pure为Python 做一个装饰器,其中一部分是能够选择性地禁止访问函数的全局范围.
有没有办法以编程方式更改哪个字典事物充当函数的全局/外部范围?
因此,例如在下面我希望能够拦截对fin 的访问h并抛出错误,但我想允许访问,g因为它是一个纯函数.
def f():
print("Non-pure function")
@pure
def g(i):
return i + 1
@pure
def h(i):
f()
return g(i)
Run Code Online (Sandbox Code Playgroud) 考虑到我有数百万个对象,其中 3 __slots__
使用短插槽名称(如xvs. long like )是否更有效would_you_like_fries_with_that_cheeseburger?
或者每个类只分配一次名称(而不是每个实例一次?)
一位朋友最近问过"CPython Interpreter如何实际处理OOP(面向对象编程)?".
这个问题最终让我困惑,因为我理解C不是面向对象的语言.
我尝试使用Google搜索,搜索StackOverflow甚至阅读CPython Wiki.但我找不到任何有用的东西.
class Person:
def __init__(self, name, age):
self.name = name
self.age = age
def getInfo(self):
return "Name: " + self.name + "\nAge: " + str(self.age)
# How the heck does CPython handle this?
personOne = Person("Bob", 34)
personTwo = Person("Rob", 26)
print( personOne.getInfo() )
print( personTwo.getInfo() )
Run Code Online (Sandbox Code Playgroud)
所以现在我真的想知道!CPython Interpreter如何处理像Objects这样的东西,如果它本身不是面向对象的?
我有一个python程序,它从文件中读取行并将它们放入dict中,简单来说,它看起来像:
data = {'file_name':''}
with open('file_name') as in_fd:
for line in in_fd:
data['file_name'] += line
Run Code Online (Sandbox Code Playgroud)
我发现它需要几个小时才能完成.
然后,我对程序做了一些改动:
data = {'file_name':[]}
with open('file_name') as in_fd:
for line in in_fd:
data['file_name'].append(line)
data['file_name'] = ''.join(data['file_name'])
Run Code Online (Sandbox Code Playgroud)
它在几秒钟内完成.
我认为这+=会使程序变慢,但似乎没有.请查看以下测试的结果.
我知道我们可以使用list append和join来提高concat字符串的性能.但我从未想过追加和加入以及添加和分配之间存在这样的性能差距.
所以我决定做更多的测试,最后发现它是dict更新操作使程序疯狂地慢.这是一个脚本:
import time
LOOPS = 10000
WORD = 'ABC'*100
s1=time.time()
buf1 = []
for i in xrange(LOOPS):
buf1.append(WORD)
ss = ''.join(buf1)
s2=time.time()
buf2 = ''
for i in xrange(LOOPS):
buf2 += WORD
s3=time.time()
buf3 = {'1':''} …Run Code Online (Sandbox Code Playgroud) 如果有人使用内置的python作为变量,删除该变量似乎将该术语的定义恢复为原始定义.例如:
set = 1
print(set)
del set
a = set([1,2,3])
print(a)
Run Code Online (Sandbox Code Playgroud)
结果:
1
{1, 2, 3}
Run Code Online (Sandbox Code Playgroud)
但是,当您从头开始删除内置函数时,不再定义它:
del set
a = set([1,2,3])
print(a)
Run Code Online (Sandbox Code Playgroud)
结果:
NameError: name 'set' is not defined
我理解使用内置函数作为变量是不好的做法,但我对这个设计决策感到好奇:
如果python源代码可以通过将删除的变量分配给它们的原始内置值来智能地恢复它们,为什么代码允许在我的第二个示例中删除内置函数?允许删除内置函数有什么可能的效用?
不,我没有现实世界的用例; 我只是想了解设计决定.
有什么方法可以挂钩 CPython 解释器,以便每个函数创建 ( def, lambda) 都会调用我定义的过程?sys.settrace而sys.setprofile不幸的是似乎并没有涵盖def和lambda。
似乎 Python 3.7 有f_trace_opcodes......早期版本有任何选择吗?
在等待长时间运行的函数完成执行时,我开始考虑垃圾回收器是否将清除对不再使用的变量的引用。
例如,我有一个类似的功能:
def long_running_function():
x = MemoryIntensiveObject()
print id(x)
# lots of hard work done here which does not reference x
return
Run Code Online (Sandbox Code Playgroud)
我对解释器是否足够聪明到足以意识到不再使用x并可以取消引用x感到好奇。测试起来有些困难,因为我可以编写代码来检查其引用计数,但是隐式地引用了它,从而避免了这样做的原因。
我的想法是,也许当函数被解析并生成字节码时,它的生成方式可能使它可以在不再引用该对象时清理该对象。
或者,答案是否更简单?只要我们仍在“可以”使用的范围内,就不会对其进行清理?
cpython ×10
python ×10
performance ×2
python-3.x ×2
bytecode ×1
c ×1
dictionary ×1
hook ×1
internals ×1
oop ×1
slots ×1
trace ×1