DELPHI盒子
!实时搜索: 盒子论坛 | 注册用户 | 修改信息 | 退出
检举帖 | 全文检索 | 关闭广告 | 捐赠
技术论坛
 用户名
 密  码
自动登陆(30天有效)
忘了密码
≡技术区≡
DELPHI技术
lazarus/fpc/Free Pascal
移动应用开发
Web应用开发
数据库专区
报表专区
网络通讯
开源项目
论坛精华贴
≡发布区≡
发布代码
发布控件
文档资料
经典工具
≡事务区≡
网站意见
盒子之家
招聘应聘
信息交换
论坛信息
最新加入: xiao2024
今日帖子: 18
在线用户: 10
导航: 论坛 -> DELPHI技术 斑竹:liumazi,sephil  
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/4/29 23:45:28
标题:
请教大神多线程高并发的问题~~~~~ 浏览:3683
加入我的收藏
楼主: 请教个问题  我用delphi 写了个dll给其他语言调用  设置了  
 IsMultiThread := TRUE; 
 
但是dll在高并发多线程下面 会出现一直等很久的情况  

查了相关资料 IsMultiThread := TRUE 是给内存申请释放加锁

所以造成在高并发下面 线程排队的情况  

函数都是局部变量 都没有操作全局变量

这样的情况 又什么办法能解决???
----------------------------------------------
-
作者:
男 msfm (清洁工) ★☆☆☆☆ -
盒子活跃会员
2016/4/30 9:56:08
1楼: 不懂在说啥
----------------------------------------------
-
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/4/30 11:36:03
2楼: msfm (清洁工)

就是delphi 编译的动态库 在多线程下面  效率低的一塌糊涂
此帖子包含附件:
PNG 图像
大小:18.1K
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2016/4/30 13:29:47
3楼: 用ScaleMM看看
----------------------------------------------
按此在新窗口浏览图片
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/4/30 17:04:48
4楼:
用ScaleMM看看



没用
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2016/4/30 18:36:55
5楼: 手动给temp变量申请内存.
----------------------------------------------
按此在新窗口浏览图片
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2016/4/30 18:42:46
6楼: 问题在于频繁的内存申请操作上.
----------------------------------------------
按此在新窗口浏览图片
作者:
男 yq97001 (yq97001) ★☆☆☆☆ -
普通会员
2016/5/1 10:14:53
7楼: 问题是线程里用了string类型,delphi的string类型,引用计数时要上锁的,所以无论多少个线程,实际只有一个线程在跑,其它的都在等,你改用widestring试一下
----------------------------------------------
-
作者:
男 roadrunner (roadrunner) ★☆☆☆☆ -
盒子活跃会员
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 多好 ~
----------------------------------------------
-
作者:
男 yq97001 (yq97001) ★☆☆☆☆ -
普通会员
2016/5/3 13:26:37
10楼: delphi多线程里用了string类型,并发是不上去的, 你看一下你贴出来的函数里,temp,str1就是string类型的,关于delphi多线程并发的时候string类型为什么上不去,我在盒子里也提出过这样的问题,并最终找到了原因。
----------------------------------------------
-
作者:
男 doorkey (DoorKey) ★☆☆☆☆ -
盒子活跃会员
2016/5/3 22:42:19
11楼: to yq97001: 在多线程里用到string也很正常啊。除非你多个线程用的string是同一个变量,不然哪里会慢到哪里去。
----------------------------------------------
QQ: 9717005 我的Blog:http://www.cnblogs.com/anydelphi/
作者:
男 iamdream (银河恒久远,梦想无止境!) ★☆☆☆☆ -
大贡献会员
2016/5/4 8:56:56
12楼: 6楼和9楼已经提示了,关键是在for循环里不断地用Concat拼接字符串,这个才是效率低的原因吧?和用不用string关系不大的。
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
男 yq97001 (yq97001) ★☆☆☆☆ -
普通会员
2016/5/4 14:32:18
13楼: 无论是单线程、多线程、只要用了string类型,就会上锁,这是他编译器的问题,网上有文章说了,从delphi5开始就是这样了,这个希望大伙认真看一下system.pas的代码,我是经过了实验和查阅了相关资料的,不是随便怀疑的。如果需要大量并发,你可以用widestring类型,如果不是并发的,用string的效率就是比widestring高
----------------------------------------------
-
作者:
男 iamdream (银河恒久远,梦想无止境!) ★☆☆☆☆ -
大贡献会员
2016/5/5 9:19:14
14楼: 楼上说的是x86汇编指令中的lock吧?这个是有影响,但基本上就是改引用计数时锁一下地址,对速度的影响应该没那么大;楼主的问题还是在循环中用了ConCat,导致不断的申请、释放内存,这个应该才是主因吧?
----------------------------------------------
-广袤璀璨的银河,永无止境的梦想(梦无止境游银河) 博客挂了……
作者:
男 letianwuji (大器晚成) ▲▲▲▲▲ -
普通会员
2016/5/5 13:08:37
15楼: 为嘛不动态跟踪看看,哪里的执行时间比较耗...比如,写个测试用例。
----------------------------------------------
相信自己,若自己都不相信,那还有谁可信。
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/5/6 10:27:35
16楼: 如果不用concat用那个来把字符串相加???小甲鱼视频说直接用+效率很低
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2016/5/6 13:02:51
17楼: 用Char数组替代string
----------------------------------------------
按此在新窗口浏览图片
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/5/6 22:27:55
18楼: 用Char数组替代string


一样的  还是有序的出来  多线程比单线程慢几十倍
----------------------------------------------
-
作者:
男 xuchuantao (暗黑天使) ★☆☆☆☆ -
普通会员
2016/5/6 23:58:50
19楼: 你把代码贴出来,不要截图.要不然没办法帮你调试.
----------------------------------------------
按此在新窗口浏览图片
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
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
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
2016/5/7 13:23:26
22楼:
bmsr 大神请问下 


StringElementSize 函数是干什么的?我用d7  没有这个函数啊~
----------------------------------------------
-
作者:
男 dawnhawk (dawnhawk) ★☆☆☆☆ -
盒子活跃会员
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
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
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年左右的机器).
----------------------------------------------
-
作者:
男 ztcjn (哎哟喂) ▲▲▲△△ -
普通会员
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楼).
----------------------------------------------
-
作者:
男 zhangl (二黑) ★☆☆☆☆ -
盒子活跃会员
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()接口函数来释放内存.
----------------------------------------------
报到
信息
登陆以后才能回复
Copyright © 2CCC.Com 盒子论坛 v3.0.1 版权所有 页面执行93.75毫秒 RSS