CLR/C#/Java/Python/IronPython/JavaScript/Lua/Ruby/Squirre l性能测试

今天蛋疼地看到一篇,考虑到已经是2年前的文章了,现在的编译器可能会进一步优化,所以自行测试了一遍。这是2007年,该文的作者拿到了最佳优化奖,但此处的代码并非最优化的,只是改进了乘方、自己实现随机数而已。(最优版本可参见和,感觉很变态…)其中,C++和C++ CLR的代码相同,只是采用的编译指令不同而已。此外,C#代码从二维数组改为一维数组,我稍微测试了一下,C#二维数组和嵌套数组的速度确实很慢。原作者的代码似乎还把下标弄错了,所以也改了下。而Python、Cython、JavaScript和Lua的代码是我自己照英特尔的原程序改编的,没有对随机数进行优化,附在文末。Squirrel的代码由dwing提供,我只是将table改成了数组,RAND_MAX + 1.0改成了32768.0的常数,时间快了约5秒左右。测试平台:CPU:Intel Core2 Duo T9400 @ 2.53GHz内存:3 GB操作系统:Windows XP Pro SP2英文版C++编译器:gcc version 4.4.1 (TDM-2 mingw32)(以下简称G++)、Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80x86(以下简称VC++ 2008)、VC++ 2010 Beta2

C++ CLR编译器:VC++ 2008、VC++ 2010 Beta2

C#编译器:Microsoft (R) Visual C# 2008 Compiler version 3.5.21022.8、Microsoft (R) Visual C# 2010 Compiler version 4.0.21006.1

Java:Java(TM) SE Runtime Environment (build 1.6.0_13-b03)

Python:Python 2.5.4 (r254:67916, Dec 23 2008, 15:10:54) [MSC v.1310 32 bit (Intel)] on win32、Python 2.6.4 (r264:75708, Oct 26 2009, 08:23:19) [MSC v.1500 32 bit (Intel)] on win32、Python 3.1.1 (r311:74483, Aug 17 2009, 17:02:12) [MSC v.1500 32 bit (Intel)] on win32

Cython:0.11.3

Psyco:1.6

IronPython:IronPython 2.6 (2.6.10920.0) on .NET 2.0.50727.1433

JavaScript:ChromePlus 1.2.6.0(Chromium 4.0.222.3 (Official Build 28644),V8 1.3.15)Lua:5.1.4

LuaJIT:1.1.5、2.0.0-beta1

Ruby:ruby 1.9.1p129 (2009-05-12 revision 23412) [i386-mswin32]

Squirrel:Squirrel 3.0 alpha 2 Copyright (C) 2003-2009 Alberto Demichelis (32 bits)顺带一提,G++是采用版(目前尚无GCC 4.4.1和4.4.2的Windows版),VC++ 2008编译器是Microsoft Visual C++ Toolkit 2008里的,C#编译器是Microsoft .NET Framework 3.5和4.0 Beta2里的,Cython和LuaJIT用的C编译器是GCC 4.4.1,LuaJIT 2.0.0还测试了VC++ 2003编译的版本,Ruby没有采用更慢的稳定版。测试时关掉了大部分占用资源的程序,每种搭配测试5次,取时间最少的一次作为最终结果。从控制台运行时似乎会影响速度(此时是C++ CLR以超过第2名3%的优势胜出),所以对于exe文件,我改成了双击运行和控制台各测5次,取最小值。测试结果:

语言/编译器

编译参数

运行时间(秒)

相对速度

C++ (G++ 4.4.1)

-O3 -s

1.765

85.84%

C++ (G++ 4.4.1)

-O3 -s -mtune=native -march=native

1.859

81.50%

C++ (G++ 4.4.1)

-O3 -s -mfpmath=sse -mtune=native -march=native

1.578

96.01%

C++ (G++ 4.4.1)

-O3 -s -mfpmath=sse -mtune=native -march=native -ffast-math

1.546

97.99%

C++ (VC++ 2008)

/O2 /MD

1.625

93.23%

C++ (VC++ 2008)

/O2 /MD /arch:SSE2

1.593

95.10%

C++ (VC++ 2008)

/O2 /MD /arch:SSE2 /fp:fast

1.562

96.99%

C++ (VC++ 2010 Beta2)

/O2 /MD

1.64

92.38%

C++ (VC++ 2010 Beta2)

/O2 /MD /arch:SSE2

1.562

96.99%

C++ (VC++ 2010 Beta2)

/O2 /MD /arch:SSE2 /fp:fast

1.531

98.95%

C++ CLR (VC++ 2008)

/O2 /MD /clr

1.578

96.01%

C++ CLR (VC++ 2010 Beta2)

/O2 /MD /clr

1.515

100.00%

C# 3.5

无参数

3.281

46.17%

C# 3.5

/o

3.219

47.06%

C# 4.0 Beta2

无参数

2.203

68.77%

C# 4.0 Beta2

/o

2.187

69.27%

Java 1.6

无参数

2.093

72.38%

Python 2.5.4

无参数

117.163

1.29%

Python 2.6.4

无参数

91.137

1.66%

Python 3.1.1

无参数

109.531

1.38%

Cython 0.11.3

-O3

11.795

12.84%

Psyco 1.6 (bind)

无参数

26.206

5.78%

Psyco 1.6 (full)

无参数

25.650

5.91%

IronPython 2.6

无参数

59.630

2.54%

JavaScript (V8 1.3.15)

无参数

16.653

9.10%

Lua 5.1.4

无参数

48.969

3.09%

Lua 5.1.4 (Luac编译)

-s

49.031

3.09%

LuaJIT 1.1.5

无参数

24.141

6.28%

LuaJIT 1.1.5

运行:-O2

9.641

15.71%

LuaJIT 1.1.5 (Luac编译)

编译:-s

24.093

6.29%

LuaJIT 1.1.5 (Luac编译)

编译:-s运行:-O2

9.641

15.71%

LuaJIT 2.0.0-beta1 (GCC 4.4.1编译)

无参数

1.546

97.99%

LuaJIT 2.0.0-beta1 (GCC 4.4.1编译)

运行:-O2

4.578

33.09%

LuaJIT 2.0.0-beta1 (GCC 4.4.1编译)

无参数

1.625

93.23%

LuaJIT 2.0.0-beta1 (VC++ 2003编译)

运行:-O2

4.578

33.09%

Ruby 1.9.1

无参数

327.797

0.46%

Squirrel 3.0 alpha 2

无参数

73.873

2.05%

Squirrel 3.0 alpha 2 (编译成字节码)

无参数

77.828

1.95%

冠军让C++ CLR夺走了,这点出乎我的意料。测试了多次,均比其他C++实现的时间要少,可见不属于测试误差。看来相对于原生代码,CLR会自动对当前平台进行优化。缺点就是体积稍大了点(29.5KB(VC++ 2010)/24KB(VC++ 2008),而其他的C++实现为7KB左右,VC++ 2008编译的还会生成1KB manifest文件),且需要安装.net framework才能运行。没有测试Intel编译器是一大遗憾,估计它才是性能王者。(由于运行库不兼容,我的电脑上无法测试;在别人的电脑上,Intel C++ 11编译器速度约为VC++2010 CLR的2倍,非常震惊。)G++在最佳的参数下和VC++基本持平,不过单一的-O3参数并没有什么优势,要组合出那么多种参数也蛮难为人的,而且-ffast-math也是不符合IEEE规范的浮点实现。顺带一提,用该参数编译未优化版本的结果是1.578秒,和优化后几乎没有区别。VC++ 2008各种参数的性能都差不多,所以不用过多考虑搭配。VC++ 2010 Beta2略微超过了VC++ 2008和G++,不过需要附带一个新的动态链接库(msvcr100.dll,749 KB)。让我无语的是C# 3.5居然远远落后于Java(慢了约53.8%),而且是在Windows操作系统上,也未测试可能更快的Java 7及IBM、DEA的JVM和GCJ。C# 4.0的性能提高了不少,只略低于Java 6了。(顺带一提,C# 2.0和3.5成绩几乎相同,看来微软在4.0上花了大气力来提升性能。)此外,C#生成的代码只有5KB,且无manifest文件。(但别忘了运行库的体积。)而Python则仅快于Ruby,比静态编译的实现慢了约2个数量级,这也在我意料之中。而在性能方面,2.6.4> 3.1.1 > 2.5.4,而3.x的表现还不错。顺带一提动态语言的多维数组都比较慢,所以改成了一维。Cython目前仍无针对数组的优化(详见),而本程序大量涉及对数组的操作,所以性能提升相当有限。此外,将列表设为了1维,速度比2维快了约50%。同时,由于Cython不能对乘方进行优化,因此我改成了乘法。Python+Psyco的组合还算不错,只增加了2行,性能就提升了约5倍,凌驾于其他动态语言之上。同上,我将乘方改成了乘法,开方则调用系统函数。IronPython的性能让我很惊讶,因为Jython的性能据说很糟糕,没想到在.net平台上会发挥得这么好。JavaScript只测试了性能最好的V8引擎。由于输出是调用DOM API,较为影响速度,所以我直接删除了。优化同上,数组采用1维。在接受dwing的建议,将全局变量和系统函数声明为local后,Lua的速度提升了1倍,表现很不错。不过Luac编译似乎没有帮助,以后不去用了。此外,同样也将table优化成了1维数组。LuaJIT 1.1.5表现非常不错,改成local声明后,速度提升了3倍,在-O2开启时居然比Cython更快。速度大约是C++的1/6,Java的1/5,相差已经在一个数量级之内了。而最近刚出的LuaJIT 2.0.0-beta1更是达到了C++的水平,这对动态语言来说简直是不可思议的。不过大部分测试是稳定在1.625秒,只有一次达到1.546。而VC++ 2003编译出来的是在1.625~1.640之间波动,但体积略小。至于兼容性,采用-O0~-O2来运行都会有大幅的性能下降(非常诡异),而且现在不支持luac编译的代码。此外,文档里也提到了,LuaJIT 2在数值计算方面接近于静态编译语言,而其他方面(例如字符串)仍略逊于后者,整体性能和JVM 1.6 Client持平。Ruby是很久没碰了,于是测试了半天,选了种最快的实现,但仍比Python 2.6.4慢了59%,速度仅有C++的1/200。代码里我用while取代了for,因为后者(无论0...n还是0.upto(n))比前者慢了一半。(Python里正好相反,于是人们会倾向于用最优雅的方式得到最好的性能。)此外数组采用了1维,乘方改成了乘法,开方用系统函数。Squirrel表现平平,和Lua相比完全出于劣势,而且我也不喜欢它的语法。顺带一提,第一次运行时为73秒,之后就一直是78秒了,编译成字节码也只能到77秒,这也是测出非编译版本更快的原因。Python和IronPython:

from random import random

from time import clock

NPARTS = 1000

NPARTS2 = NPARTS * 2

NITER = 201

DIMS = 3

pot = .0

SIZE = NPARTS * DIMS

r = [.0]* SIZE

def computePot():

global NPARTS, DIMS, r, pot

for i in xrange(NPARTS):

for j in xrange(i - 1):

distx = r[j] - r[i]

disty = r[NPARTS + j] - r[NPARTS + i]

distz = r[NPARTS2 + j] - r[NPARTS2 + i]

dist = (distx * distx + disty * disty + distz * distz) ** .5

pot += 1.0 / dist

def initPositions():

global NPARTS, DIMS, r

for i in xrange(SIZE):

r[i] = 0.5 + random()

def updatePositions():

global NPARTS, DIMS, r

for i in xrange(SIZE):

r[i] -= 0.5 + random()

def main():

global pot, NITER

initPositions()

updatePositions()

start = clock()

for i in xrange(NITER):

pot = .0

computePot()

if not i % 10:

print "%5d: Potential: %10.7f" % (i, pot)

updatePositions()

stop = clock()

print "Seconds = %10.9f" % (stop - start)

if __name__ == '__main__':

main()

Python 3000:将Python的代码中,print改成函数调用形式(加括号),xrange改成range即可。Cython:

from random import random

from time import clock

cdef int NPARTS = 1000

cdef int NPARTS2 = NPARTS * 2

cdef int NITER = 201

cdef int DIMS = 3

cdef int SIZE = NPARTS * DIMS

cdef double pot = .0

cdef list r = [.0]* SIZE

cpdef computePot():

global NPARTS, DIMS, r, pot

cdef int i, j

cdef double distx, disty, distz, dist

for i in xrange(NPARTS):

for j in xrange(i - 1):

distx = r[j] - r[i]

disty = r[NPARTS + j] - r[NPARTS + i]

distz = r[NPARTS2 + j] - r[NPARTS2 + i]

dist = (distx * distx + disty * disty + distz * distz) ** .5

pot += 1.0 / dist

cpdef initPositions():

global NPARTS, DIMS, r

cdef int i, j

for i in xrange(SIZE):

r[i] = 0.5 + random()

cpdef updatePositions():

global NPARTS, DIMS, r

cdef int i, j

for i in xrange(SIZE):

r[i] -= 0.5 + random()

def main():

global pot, NITER

cdef int i

cdef double start, stop

initPositions()

updatePositions()

start = clock()

for i in xrange(NITER):

pot = .0

computePot()

if not i % 10:

print "%5d: Potential: %10.7f" % (i, pot)

updatePositions()

stop = clock()

print "Seconds = %10.9f" % (stop - start)

Psyco(使用bind()):

from random import random

from time import clock

from math import sqrt

from psyco import bind

NPARTS = 1000

NITER = 201

DIMS = 3

pot = .0

r = [[.0]* NPARTS] * DIMS

def computePot():

global NPARTS, DIMS, r, pot

for i in xrange(NPARTS):

for j in xrange(i - 1):

distx = (r[0][j] - r[0][i])

distx *= distx

disty = (r[1][j] - r[1][i])

disty *= disty

distz = (r[2][j] - r[2][i])

distz *= distz

dist = sqrt(distx + disty + distz)

pot += 1.0 / dist

def initPositions():

global NPARTS, DIMS, r

for i in xrange(DIMS):

for j in xrange(NPARTS):

r[i][j] = 0.5 + random()

def updatePositions():

global NPARTS, DIMS, r

for i in xrange(DIMS):

for j in xrange(NPARTS):

r[i][j] -= 0.5 + random()

def main():

global pot, NITER

initPositions()

updatePositions()

start = clock()

for i in xrange(NITER):

pot = .0

computePot()

if not i % 10:

print "%5d: Potential: %10.7f" % (i, pot)

updatePositions()

stop = clock()

print "Seconds = %10.9f" % (stop - start)

bind(computePot)

bind(initPositions)

bind(updatePositions)

bind(main)

if __name__ == '__main__':

main()

Psyco(使用full()):

from random import random

from time import clock

from math import sqrt

from psyco import full

full()

NPARTS = 1000

NITER = 201

DIMS = 3

pot = .0

r = [[.0]* NPARTS] * DIMS

def computePot():

global NPARTS, DIMS, r, pot

for i in xrange(NPARTS):

for j in xrange(i - 1):

distx = (r[0][j] - r[0][i])

distx *= distx

disty = (r[1][j] - r[1][i])

disty *= disty

distz = (r[2][j] - r[2][i])

distz *= distz

dist = sqrt(distx + disty + distz)

pot += 1.0 / dist

def initPositions():

global NPARTS, DIMS, r

for i in xrange(DIMS):

for j in xrange(NPARTS):

r[i][j] = 0.5 + random()

def updatePositions():

global NPARTS, DIMS, r

for i in xrange(DIMS):

for j in xrange(NPARTS):

r[i][j] -= 0.5 + random()

def main():

global pot, NITER

initPositions()

updatePositions()

start = clock()

for i in xrange(NITER):

pot = .0

computePot()

if not i % 10:

print "%5d: Potential: %10.7f" % (i, pot)

updatePositions()

stop = clock()

print "Seconds = %10.9f" % (stop - start)

if __name__ == '__main__':

main()

我顺便还写了个numpy的实现:

from numpy import add, square

from numpy.random import rand

from time import clock

NPARTS = 1000

NITER = 201

DIMS = 3

r = rand(NPARTS, DIMS)

pot = .0

def computePot():

global NPARTS, DIMS, r, pot

for i in xrange(NPARTS):

for j in xrange(i - 1):

pot += 1.0 / (add.reduce(square(r[j] - r[i])) ** .5)

def initPositions():

global r

r += 0.5

def updatePositions():

c = clock()

print c

global DIMS, NPARTS, r

r -= (rand(NPARTS, DIMS) + .5)

print clock() -c

def main():

global pot, NITER

initPositions()

updatePositions()

start = clock()

for i in xrange(NITER):

pot = .0

computePot()

if not i % 10:

print "%5d: Potential: %10.7f" % (i, pot)

updatePositions()

stop = clock()

print "Seconds = %10.9f" % (stop - start)

if __name__ == '__main__':

main()

然而让我无语的是,numpy版比纯Python版还慢1个数量级。稍微测试了一下,发现了原因:numpy的函数调用开销很大,因此不适合对小数组进行操作。简单来说,计算二维数组里2列间差的平方和时,numpy调用了3次函数,而纯Python则完全是内置操作符,所以调用开销较小。而这个二维数组每列只有3个数,所以即便numpy的函数计算很快,但总体来说仍慢于纯Python版。不过对付大数组则是numpy占据优势了:在数组长度为3时,numpy比Python慢10倍;长度为33时,2者持平;长度为330时,numpy快8倍;长度为3300时,numpy快30倍。(纯Python版的时间复杂度基本可视为O(N)。)JavaScript:

var NPARTS = 1000;

var NPARTS2 = 2000;

var NITER = 201;

var DIMS = 3;

var SIZE = DIMS * NPARTS;

var r = new Array(SIZE);

var pot;

function initPositions() {

for(var i = 0; i < SIZE; i++)

r[i] = 0.5 + Math.random();

}

function updatePositions() {

for (var i = 0; i < SIZE; i++)

r[i] -= 0.5 + Math.random();

}

function computePot() {

for (var i = 0; i < NPARTS; i++ ) {

for (var j = 0, k = i - 1; j < k; j++ ) {

var distx = r[j] - r[i];

var disty = r[NPARTS + j] - r[NPARTS + i];

var distz = r[NPARTS2 + j] - r[NPARTS2 + i];

var dist = Math.sqrt(distx * distx + disty * disty + distz * distz);

pot += 1.0 / dist;

}

}

}

initPositions();

updatePositions();

var start = new Date();

for (var i = 0; i < NITER; i++) {

pot = 0.0;

computePot();

updatePositions();

}

var stop = new Date();

alert(stop - start);

Lua:

local NPARTS = 1000

local NITER = 201

local DIMS = 3

local NPARTS2 = 2000

local SIZE = DIMS * NPARTS

local pot = .0

local r = {}

local sqrt = math.sqrt

local random = math.random

function computePot()

for i = 1, NPARTS do

for j = 1, i - 1 do

local distx = r[j] - r[i]

local disty = r[NPARTS + j] - r[NPARTS + i]

local distz = r[NPARTS2 + j] - r[NPARTS2 + i]

pot = pot + 1.0 / sqrt(distx * distx + disty * disty + distz * distz)

end

end

end

function initPositions()

for i = 1, SIZE do

r[i] = 0.5 + random()

end

end

function updatePositions()

for i = 1, SIZE do

r[i] = r[i] - (0.5 + random())

end

end

initPositions()

updatePositions()

local start = os.clock()

for i = 1, NITER do

pot = .0

computePot()

if i % 10 == 0 then

print(string.format("%5d: Potential: %10.7f", i, pot))

end

updatePositions()

end

local stop = os.clock()

print(string.format("Seconds = %10.9f", stop - start))

Ruby:

$NPARTS = 1000

$NPARTS2 = 2000

$NITER = 201

$DIMS = 3

$SIZE = $DIMS * $NPARTS

$pot = 0.0

$r = [0.0]* ($NPARTS * $DIMS)

def computePot()

i = 0

while i < $NPARTS

j = 0

max = i - 1

while j < max

distx = $r[j] - $r[i]

disty = $r[$NPARTS + j] - $r[$NPARTS + i]

distz = $r[$NPARTS2 + j] - $r[$NPARTS2 + i]

$pot = $pot + 1.0 / Math.sqrt(distx * distx + disty * disty + distz * distz)

j += 1

end

i += 1

end

end

def initPositions()

i = 0

while i < $SIZE

$r[i] = 0.5 + rand()

i += 1

end

end

def updatePositions()

i = 0

while i < $SIZE

$r[i] -= 0.5 + rand()

i += 1

end

end

initPositions()

updatePositions()

start = Time.now()

i = 0

while i < $NITER

pot = 0.0

computePot()

if i % 10 == 0

print "%5d Potential %10.7f\n" % [i, $pot]

end

updatePositions()

i += 1

end

stop = Time.now()

print "Seconds = %10.9f\n" % (stop - start)

Squirrel:

const NPARTS = 1000

const NITER = 201

const DIMS = 3

const NPARTS2 = 2000

const RANDMAX= 32168.0

local SIZE = DIMS * NPARTS

local pot = 0.0

local r = []

local sqrt = sqrt

local rand = rand

local function computePot() {

for(local i = 0; i < NPARTS; ++i) {

for(local j = 0, k = i-1; j < k; ++j) {

local distx = r[j] - r[i]

local disty = r[NPARTS+ j] - r[NPARTS+ i]

local distz = r[NPARTS2 + j] - r[NPARTS2 + i]

pot += 1.0 / sqrt(distx * distx + disty * disty + distz * distz)

}

}

}

local function initPositions() {

for(local i = 0; i < SIZE; ++i) {

r.append(0.5 + rand() / RANDMAX)

}

}

local function updatePositions() {

for(local i = 0; i < SIZE; ++i) {

r[i] -= 0.5 + rand() / RANDMAX

}

}

initPositions()

updatePositions()

local start = clock()

for(local i = 0; i < NITER; ++i) {

pot = 0.0

computePot()

if(i % 10 == 0) {

print(format("%5d: Potential: %10.7f\n", i, pot))

}

updatePositions()

}

local stop = clock()

print(format("Seconds = %10.9f\n", stop - start))

你可能还会对下列文章感兴趣:

python js 性能_lua与python性能测试比较相关推荐

  1. python js 性能_Python Json使用,Json库性能测试

    介绍 官网:https://www.json.org/json-zh.html 中文介绍:https://www.json.cn/wiki.html 中文介绍:https://developer.mo ...

  2. Atitit.提升软件Web应用程序 app性能的方法原理 h5 js java c# php python android .net

    Atitit.提升软件Web应用程序 app性能的方法原理 h5 js java c# php python android .net 1. 提升单例有能力的1 2. 减少工作数量2 2.1. 减少距 ...

  3. 基于python的界面自动化测试-Python实现性能自动化测试竟然如此简单

    一.思考❓❔ 1.什么是性能自动化测试? 性能系统负载能力超负荷运行下的稳定性系统瓶颈自动化测试使用程序代替手工提升测试效率性能自动化使用代码模拟大批量用户让用户并发请求多页面多用户并发请求采集参数, ...

  4. 怎么自学python自动化测试-Python实现性能自动化测试竟然如此简单

    一.思考❓❔ 1.什么是性能自动化测试? 性能系统负载能力超负荷运行下的稳定性系统瓶颈自动化测试使用程序代替手工提升测试效率性能自动化使用代码模拟大批量用户让用户并发请求多页面多用户并发请求采集参数, ...

  5. python程序分析,用Python编写分析Python程序性能的工具的教程

    用Python编写分析Python程序性能的工具的教程 来源:中文源码网    浏览: 次    日期:2018年9月2日 [下载文档:  用Python编写分析Python程序性能的工具的教程.tx ...

  6. python自动化测试-Python实现性能自动化测试竟然如此简单

    一.思考❓❔ 1.什么是性能自动化测试? 性能系统负载能力超负荷运行下的稳定性系统瓶颈自动化测试使用程序代替手工提升测试效率性能自动化使用代码模拟大批量用户让用户并发请求多页面多用户并发请求采集参数, ...

  7. JS 逆向的时候 Python 如何调用 JavaScript 代码?「建议收藏哦!」

    你好,我是悦创.关注公众号:AI悦创,抢先阅读优质文章. 公众号原文:https://mp.weixin.qq.com/s/PYEiSMgP2LT0DmcHX08PCw 博客原文:https://ww ...

  8. 对c++ Java go python js 的一些总结

    文章目录 编译执行和解释执行 面向过程和面向对象 动静态和强弱类型 静态语言和动态语言 强类型和弱类型 对c++ Java go python js 的一些总结 编译执行和解释执行 1.编译执行:将源 ...

  9. rust python扩展_Rust语言优化Python性能案例

    原标题:Rust语言优化Python性能案例 导读:Python 被很多互联网系统广泛使用,但在另外一方面,它也存在一些性能问题,不过 Sentry 工程师分享的在关键模块上用另外一门语言 Rust ...

最新文章

  1. 用 Flask 来写个轻博客 (10) — M(V)C_Jinja 常用过滤器与 Flask 特殊变量及方法
  2. using namespace cv_闪耀暖暖万圣节非凡魔女南瓜套公开 消耗钻石获取 大喵无CV
  3. robot连接mysql_robot连接mysql - autocar - 51Testing软件测试网 51Testing软件测试网-软件测试人的精神家园...
  4. console.dir有很多浏览器,系统的兼容性问题,不要随便用!
  5. java模拟登陆_java-模拟登陆练习(示例代码)
  6. Can not find the tag library descriptor for http://java.sun.com/jsp/jstl/core
  7. blender 3d打印_如何在Blender中开始3D打印
  8. 从“做什么”到“怎么做”,说说一只蚊子
  9. mybatis mysql触发器_MyBatis创建Oracle触发器
  10. LeetCode笔记
  11. 立潮头 筑根基 赢未来——ZDNS合作伙伴大会成功举办
  12. Typora 段落如何快速首行缩进两个字符
  13. Windows + Linux 双系统的安装
  14. 信息学奥赛一本通:题解目录 (〃‘▽‘〃)点个赞吧
  15. hlg2146【多维背包】
  16. 手机上好用的APP推荐
  17. pandas批量处理体育成绩
  18. 编写一个python程序判断用户输入的8位银行卡_用Python编写的程序,提示用户输入一个由7位数字组成的帐号?...
  19. JQ获取元素的父子兄弟级
  20. 小天软件园程序源码 一款纯发布软件程序

热门文章

  1. bootstrap table固定列导致复选框失效的解决方法
  2. 心血来潮,开通了博客
  3. 【LaTex的PPT模板集】- (亲测有效)在线PPT模板及其使用方法,overleaf与TeXstudio支持中文方法
  4. 傅里叶特征学习高频:Fourier Features Let Networks Learn High Frequency Functions in Low Dimensional Domains
  5. c 语言爱心告白代码,c语言心形告白代码实现
  6. 前端工程师成长之多看好书
  7. 对Send()函数的一些理解
  8. 推特CEO杰克·多西去年薪酬仅1.4美元 没有任何股票奖励
  9. 快速入门Tableau系列 | Chapter13【雷达图和凹凸图】
  10. android fragment相机,简单的易于集成的Android相机Fragment – Camer...