Comments (23)
这个问题好像上次zs群主提出过,也是同样的解决办法
from delphi-cross-socket.
我的fork上传了一份菜根修改的代码,可以参考一下
from delphi-cross-socket.
from delphi-cross-socket.
如果把HttpServer定义成TCrossHttpServer就会发生问题,但不代表定义成接口没问题!
先看看定义TCrossHttpServer
from delphi-cross-socket.
然后你上面传的图2也可以看出,AOwner: ICrossSocket传进来时是3,TIocpListen.Create后就是2了
from delphi-cross-socket.
不过如果CreateListen(Const AOwner: ICrossSocket;...
加上const也可以
from delphi-cross-socket.
这也是无意发现的问题,应该是五月定义成TCrossHttpServer才发现这个问题的
当然如果传入时 加const好像直接不调用addref和release计数为0也不释放,是不是会提高点效率?
from delphi-cross-socket.
这个也是五月的使用方法不当,这个也算delphi的接口陷阱吧
from delphi-cross-socket.
在正常使用下,最好将所有记录类型、字符、对象、接口、数组等类型以 const 定义传递能节省很大效率,防止编译器自动插入引用计数或复制副本等指令,通过调试查看汇编码的生成就能看到,所有这些在没有加 const 时才会由编译器自动插入一些指令,当然事无绝对,某些场景下可以根据需求来对 const 进行使用
from delphi-cross-socket.
受教了,谢谢楼上
from delphi-cross-socket.
you can also avoid to use string as buffers, if needed to concatenate use Tstringbuilder,
avoid to pcasting string buffers using string[1], because everytime this call @uniquestring and a new @UnicodeString, you can access the string using pointer or Pbyte^ where the content is
anyway is better use a TBytes to treat the buffering, and only at the endpoint, if you need to convert to string use TEncoding.ASCII.(or UTF8).GetString(TBytes)
or you can use directly pointers with GetMem,FreeMem
also using too much strings for buffering, into a intensive operations as server, will degrade the heap
from delphi-cross-socket.
我之所以使用接口,就是看中了接口的自动引用计数机制,函数的接口参数我也是故意不加const修饰的,因为加了const,调用函数时引用计数就不会+1了,这个+1恰恰是我需要的,我需要在函数调用过程中,由引用计数保证接口参数一直有效
感谢各位热心的提出各种建议和意见,相信有你们的帮助,这套库会越来越好的,请继续保持热情、保持关注
from delphi-cross-socket.
我之所以使用接口,就是看中了接口的自动引用计数机制,函数的接口参数我也是故意不加const修饰的,因为加了const,调用函数时引用计数就不会+1了,这个+1恰恰是我需要的,我需要在函数调用过程中,由引用计数保证接口参数一直有效
感谢各位热心的提出各种建议和意见,相信有你们的帮助,这套库会越来越好的,请继续保持热情、保持关注
谢谢解答!
from delphi-cross-socket.
另外写idefixpack的大牛andy发表过一篇文章,是说interface速度比Object慢很多,有人建议关键单元不要用接口设计!
这个是andy发的文章:
https://andy.jgknet.de/blog/2016/05/whats-wrong-with-virtual-methods-called-through-an-interface/
from delphi-cross-socket.
Interface 这个东西怎么说呢,如果要求效率而言,肯定是没有 object 快,打个比方,一般 object 或 interface 对于子类或子接口继承关系的类型转换都是使用 as 关键字完成,而 as 如果大量使用的话是很影响性能的,但 object 可使用 MyObject := TObjectXXX(Instance) 这种方式进行强转,性能几乎不计,因为它们指向的地址是一致的,而 interface 做不到 MyIntf := IInterfaceXXX(Instance),它必须通过 as 关键字并由编译器插入 Interface.QueryInterface 查表的代码实现方式处理,具体它的内部实现可看源码,所以涉及到接口类型的转换还是涉及到一些性能问题的,这里还包括接口中方法的一些调用不像 object 那么直接等。
另外对于以接口作为参数的使用,有时应该考虑下是否需要 const 关键字的必要性,比如以下代码在使用时最好加入 const ,而减少不必要的引用计数开销:
procedure test(A: ITest);
begin
// same code...
end;
procedure main;
var
Intf: ITest;
begin
Intf := TTest.Create;
test(Intf);
end;
在某个方法中初始的接口实例,然后由该方法中的子方法执行相应的接口操作时,对接口参数不加 const 关键字完全是对性能的浪费,如果 test 中的接口参数定义为 const 传递,但在 main 方法结束后导致接口释放异常,这个锅铁定得由 main 方法中的 test 子方法背的,只要 test 方法在使用该接口参数时正常访问及传递,几乎不会出现引用计数为 0 而在子方法中被异常释放的可能性。所以接口以 const 方式传递,并在与之有关的子方法中正常调用访问,几乎不存在接口引用计数异常的问题,如果有,那就得好好检测子方法的代码使用方式了
在比如,如果真的在某个子子方法中需要接口的引用计数做特殊的操作,完全可以这样:
procedure test2(A: ITest);
begin
// 编译器插入引用计数加 1
// user same code
// 编译器插入引用计数减 1
end;
proceudre test(const A: ITest);
begin
test2(A);
end;
再或者某些结构中有对应的接口实现,并赋值,只要不特别加入 weak 或 unsafe ,编译器都会自动对结构体中的赋值插入接口引用计数代码。
所以接口参数在最顶层的方法一路传递下来时,最顶层的那个方法最好使用 const 关键符,由后面的子方法决定什么时候需要由编译器自动增加引用计数
from delphi-cross-socket.
well the low level layer, cpu intensive as the sockets binded to IOCP, using base class, or TObject root without rely on interface management, we will have an enhancement
I have still not read the code, but read/write in the sockets should not lookup the interface table every time, a normal class will be faster and suitable
also consider 100K sockets, we have already one global TDictionary <Uint64, connection> at the top layer (and it's the best way to manage them for direct lookups), so let's avoid interface joining, binding, and lookup times too
(if can be done)
from delphi-cross-socket.
well the low level layer, cpu intensive as the sockets binded to IOCP, using base class, or TObject root without rely on interface management, we will have an enhancement
I have still not read the code, but read/write in the sockets should not lookup the interface table every time, a normal class will be faster and suitable
also consider 100K sockets, we have already one global TDictionary <Uint64, connection> at the top layer (and it's the best way to manage them for direct lookups), so let's avoid interface joining, binding, and lookup times too
(if can be done)
你这个问题我之前使用的方式是给基类加一个indexId,查找时根据indexId直接定位,
myobj := objects[indexId];这样就节省了查找时间
from delphi-cross-socket.
I'm talking of replace Interface of the sockets binded to IOCP with a standard "class", never we should do a lookup into a list or hash, or automatic getmem freemem,
when you access the object the methods are retrieved directly through a direct jump into VMT address
at high level it's ok as now to use TDictionary for lookup ID->object, is the faster (generic associative array pair <key, pointer>)
from delphi-cross-socket.
你说的这个上面提出过,建议关键单元的基础类使用TObject而不是Interfaced
from delphi-cross-socket.
we can use a lineprofiler as the nexusdb.com quality suite to see where the CPU time is involved,
often is enough to rewrite a pair of functions of a server software to obtain bottleneck free and speed raise
from delphi-cross-socket.
另外再多一句嘴,以这个框架现有的架构,将最底层抽象出的 Interface 改成 TObject,对作者不是一个简单的小活,真要调整,估计得花些时间精力
from delphi-cross-socket.
这确实是个问题,不过我看了tcp部分还是容易改的,http部分复杂了
from delphi-cross-socket.
抱歉,我绝不会为了这一点点性能提升而放弃接口带来的便利
若有不同意见,你们可以自己尝试改成 TObject 然后对比一下性能,你就会发现纯属浪费时间
from delphi-cross-socket.
Related Issues (20)
- WebSocket Server中如何开启压缩功能?以及发送Ping控制帧? HOT 4
- Use English as default HOT 5
- httpclient连接自签名服务器失败 HOT 2
- linux下进行百万请求压测过段时间请求就会无响应 HOT 4
- websocket 提交长字符串的时候,服务方没有反应,但是提交短字符串的时候,没有问题,使用其他控件长字符串没问题。 HOT 2
- WebSocketClient连接C#的WebSocket生成Key有问题 HOT 1
- websocket 使用ssl后,自带demo连接正常,用以下网址连接测试,会发生握手失败 HOT 2
- WebSocketServer例子编译不了 HOT 1
- 调试WebSocket时发现一出内存泄漏 HOT 2
- 当使用websocket的时候,AUrl是 'ws://xxxx',协议应该是 http。 应用目录里面没有libcripto.dll。 HOT 9
- TCrossHttpUtils.ExtractUrl 解析url的时候,没有考虑 ws://127.0.0.1:8080 的情况,如果后面没有APath. HOT 2
- 自带的demo在ios下编译出错 HOT 1
- WebSocket客户端连接服务端还没准备好,服务端就返回封包了.导致错过了第一条封包. HOT 6
- 请问怎么使用webservice的session呢? HOT 1
- ios下仍然报错 HOT 2
- ICrossConnection 是否可以添加一个预留的指针用来保存和他关联的某个对象?类似于控件的tag, 或者 ListBoxItem 里面的tagObject。 HOT 2
- ICrossServer开启SSL后一个奇怪的问题 HOT 5
- 遇到一个SSL莫名其妙的问题,请教一下
- Net.CrossSocket.Base.pas _Log 在debug模式下,報内存分配和非法訪問的錯誤。 HOT 1
- 最近更新到最新版本,報了幾次這個異常。 TCrossWebSocketClientConnection._WebSocketRecv
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from delphi-cross-socket.