导航:
论坛 -> DELPHI技术
斑竹:liumazi,sephil
作者:
2016/4/29 23:45:28
标题:
请教大神多线程高并发的问题~~~~~
浏览:3706
加入我的收藏
楼主:
请教个问题 我用delphi 写了个dll给其他语言调用 设置了 IsMultiThread := TRUE; 但是dll在高并发多线程下面 会出现一直等很久的情况 查了相关资料 IsMultiThread := TRUE 是给内存申请释放加锁 所以造成在高并发下面 线程排队的情况 函数都是局部变量 都没有操作全局变量 这样的情况 又什么办法能解决???
----------------------------------------------
-
作者:
msfm (清洁工)
★☆☆☆☆
-
盒子活跃会员
2016/4/30 9:56:08
1楼:
不懂在说啥
----------------------------------------------
-
作者:
2016/4/30 11:36:03
2楼:
msfm (清洁工) 就是delphi 编译的动态库 在多线程下面 效率低的一塌糊涂
此帖子包含附件: 大小: 18.1K
----------------------------------------------
-
作者:
2016/4/30 13:29:47
3楼:
用ScaleMM看看
----------------------------------------------
作者:
2016/4/30 17:04:48
4楼:
没用
----------------------------------------------
-
作者:
2016/4/30 18:36:55
5楼:
手动给temp变量申请内存.
----------------------------------------------
作者:
2016/4/30 18:42:46
6楼:
问题在于频繁的内存申请操作上.
----------------------------------------------
作者:
2016/5/1 10:14:53
7楼:
问题是线程里用了string类型,delphi的string类型,引用计数时要上锁的,所以无论多少个线程,实际只有一个线程在跑,其它的都在等,你改用widestring试一下
----------------------------------------------
-
作者:
2016/5/2 11:34:47
8楼:
明明是处理PChar, 为何要牵扯上String, 首先Getmem(Result,strlen(str)*3)为Result分配足够大的内存, 填充好Result的内容后再用Reallocmem(Result,Size)释放多余的空间, 整个处理函数最简洁的实现方法完全用不到string
----------------------------------------------
-
作者:
lsuper (lsuper)
★☆☆☆☆
-
盒子活跃会员
2016/5/2 23:58:25
9楼:
嗯,for ... concat,也是醉了 1、参考楼上 roadrunner (roadrunner) 预分配的做法吧 ~ 2、如果用 ScaleMM 封装的 DLL 注意 ShareMM 问题 3、如果就这么个函数不建议封 dll,直接整合到 exe 加 inline 多好 ~
----------------------------------------------
-
作者:
2016/5/3 13:26:37
10楼:
delphi多线程里用了string类型,并发是不上去的, 你看一下你贴出来的函数里,temp,str1就是string类型的,关于delphi多线程并发的时候string类型为什么上不去,我在盒子里也提出过这样的问题,并最终找到了原因。
----------------------------------------------
-
作者:
2016/5/3 22:42:19
11楼:
to yq97001: 在多线程里用到string也很正常啊。除非你多个线程用的string是同一个变量,不然哪里会慢到哪里去。
----------------------------------------------
QQ: 9717005 我的Blog:http://www.cnblogs.com/anydelphi/
作者:
2016/5/4 8:56:56
12楼:
6楼和9楼已经提示了,关键是在for循环里不断地用Concat拼接字符串,这个才是效率低的原因吧?和用不用string关系不大的。
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
2016/5/4 14:32:18
13楼:
无论是单线程、多线程、只要用了string类型,就会上锁,这是他编译器的问题,网上有文章说了,从delphi5开始就是这样了,这个希望大伙认真看一下system.pas的代码,我是经过了实验和查阅了相关资料的,不是随便怀疑的。如果需要大量并发,你可以用widestring类型,如果不是并发的,用string的效率就是比widestring高
----------------------------------------------
-
作者:
2016/5/5 9:19:14
14楼:
楼上说的是x86汇编指令中的lock吧?这个是有影响,但基本上就是改引用计数时锁一下地址,对速度的影响应该没那么大;楼主的问题还是在循环中用了ConCat,导致不断的申请、释放内存,这个应该才是主因吧?
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
2016/5/5 13:08:37
15楼:
为嘛不动态跟踪看看,哪里的执行时间比较耗...比如,写个测试用例。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
2016/5/6 10:27:35
16楼:
如果不用concat用那个来把字符串相加???小甲鱼视频说直接用+效率很低
----------------------------------------------
-
作者:
2016/5/6 13:02:51
17楼:
用Char数组替代string
----------------------------------------------
作者:
2016/5/6 22:27:55
18楼:
用Char数组替代string 一样的 还是有序的出来 多线程比单线程慢几十倍
----------------------------------------------
-
作者:
2016/5/6 23:58:50
19楼:
你把代码贴出来,不要截图.要不然没办法帮你调试.
----------------------------------------------
作者:
2016/5/7 0:31:14
20楼:
//URL编码 UTF8 and gbk function URLencode(const str: PChar; Utf8: bool): PChar; stdcall; var i, len: integer; temp, Str1: string; begin if Utf8 = True then Str1:= AnsiToUtf8(str) //Result:= PChar(HttpEncode(UTF8Encode(str))) else str1:= str; //Result:= PChar(HttpEncode(str)); len := length(Str1); for i := 1 to len do begin if (Str1[i] in ['0'..'9']) or (Str1[i] in ['-', '_', '.', '/']) or (Str1[i] in ['A'..'Z']) or (Str1[i] in ['a'..'z']) then begin temp := temp + Str1[i]; continue; end; temp := temp + '%' + inttohex(integer(Str1[i]), 0); end; Result := PChar(temp); end;
----------------------------------------------
-
作者:
bmsr (白忙剩人)
★☆☆☆☆
-
普通会员
2016/5/7 3:11:10
21楼:
function URLencode(const str: PChar; Utf8: bool): PChar; stdcall; var i, len, charSize: integer; maxSize, actSize: integer; p: pointer; index: integer; wrd: string[4]; begin charSize := StringElementSize(str); len := Length(str); maxSize := len * (charSize * 5) + sizeof(char); //若所有字符都不符合时所占的最大内存 getmem(result, maxSize); //这里申请内存一次 actSize := 0; //实际使用字节数设为0; index := 0; p := @result[index]; //p 指向result的第一个字节地址 for i := 1 to len do begin if CharInSet(str[i], ['0' .. '9', '-', '_', '.', '/', 'A' .. 'Z', 'a' .. 'z']) then begin move(str[i], p^, charSize); // actSize := actSize + charSize; inc(index); p := @result[index]; //移动指针,指向下次需要移动的目的 end else begin result[index] := '%'; inc(index); p := @result[index]; wrd := inttohex(word(str[i]), 0); move(wrd[1], p^, 4); inc(index, 4); p := @result[index]; actSize := actSize + charSize * 5; end; end; result[index] := #0; inc(index); actSize := actSize + charSize; p := @result[index]; FreeMem(p, maxSize - actSize); //释放多余的内存 释放一次 总共两次内存操作 end; 未调试,思路大概就是这样
----------------------------------------------
http://blog.sina.com.cn/bmsrnote
作者:
2016/5/7 13:23:26
22楼:
StringElementSize 函数是干什么的?我用d7 没有这个函数啊~
----------------------------------------------
-
作者:
2016/5/7 15:08:03
23楼:
D7版本低了,Seattle有这个函数: http://docwiki.embarcadero.com/Libraries/Seattle/en/System.StringElementSize function StringElementSize(const S: UnicodeString): Word; overload; Returns the number of bytes that represent a character in the string. Call StringElementSize to obtain the number of bytes necessary to represent one character in the current string. Calling StringElementSize for Unicode strings always returns a result of 2.
----------------------------------------------
-
作者:
bmsr (白忙剩人)
★☆☆☆☆
-
普通会员
2016/5/7 18:38:39
24楼:
StringElementSize 求的是字符串单个字节所占byte数,如果明确可以直接用数字代替
----------------------------------------------
http://blog.sina.com.cn/bmsrnote
作者:
2016/5/7 18:40:24
25楼:
好的 非常感谢 ~感谢各位大大的帮助 ~~~ 另外还有个问题 我在delphi里面多次用到concat 有什么办法替代吗?
----------------------------------------------
-
作者:
bmsr (白忙剩人)
★☆☆☆☆
-
普通会员
2016/5/7 18:47:48
26楼:
+
----------------------------------------------
http://blog.sina.com.cn/bmsrnote
作者:
datm (dATM)
★☆☆☆☆
-
盒子活跃会员
2016/5/28 10:21:13
27楼:
System.NetEncoding.TURLEncoding.URL.Encode
----------------------------------------------
-
作者:
sspeak (sspeak)
★☆☆☆☆
-
盒子活跃会员
2016/5/28 11:29:48
28楼:
字符串+,每一次+都会引起内存重分配(内存管理器可能有优化),在大循环次数时,会对性能有very very大的影响. 比如base64编码,size=几M,所费时间,一次性分配内存是几秒,+是二十分钟(96年左右的机器).
----------------------------------------------
-
作者:
2016/5/30 11:07:48
29楼:
字符串+,每一次+都会引起内存重分配(内存管理器可能有优化),在大循环次数时,会对性能有very very大的影响. 比如base64编码,size=几M,所费时间,一次性分配内存是几秒,+是二十分钟(96年左右的机器).
那用什么替代??还是无解?
----------------------------------------------
-
作者:
bjzhq ( oce)
★☆☆☆☆
-
盒子活跃会员
2016/5/30 22:01:55
30楼:
TStringBuilder
----------------------------------------------
-
作者:
sspeak (sspeak)
★☆☆☆☆
-
盒子活跃会员
2016/5/31 19:58:45
31楼:
8楼,最普适的做法.也可以30楼. 对于具体的,UrlEncode,好像delphi有自带(27楼).
----------------------------------------------
-
作者:
2016/6/1 9:23:58
32楼:
首先 temp: string; 是栈上的变量, 函数调用结束后, temp生命周期结束,会释放字符串占用的空间, 那你的代码最后 Result:= PChar(temp); 这样做真的不会报错吗? 实际上这时候函数返回值是个悬空指针, 当你用这个指针取数据的时候, 这段内存里的数据很可能已经被改写了. 其次, 设计接口函数, 是不是借鉴windows api的做法更好一些呢? function URLencode(output: PChar; Len: Integer; const str: PChar; Utf8: bool): PChar; stdcall; 由调用者申请空间, 传入首地址和长度即可, 如果按照你的做法, 在函数内部申请空间, 那么你的dll就要提供free()接口函数来释放内存.
----------------------------------------------
报到