我在Azure上看到了很多关于在WCF中禁用Nagle算法的帖子.我一直想知道这是否仅适用于Azure,或者这应该是更通用的最佳实践.
如各种来源所述,Nagle算法基本上将小TCP请求批处理为单个更大的请求.批量发生在每个连接的基础上.
我在专业环境中看到的大多数WCF传输都是小块数据,由单个线程发送,大多数是双向的.我知道这对于Nagle算法来说并不是理想的情况.
那么......我的结论是否正确,在使用WCF或SOAP时,无论上下文如何,最好始终禁用它?
我最近想知道.NET中内部如何lock(或更具体Monitor:)在锁定的对象方面工作.具体来说,我想知道开销是什么,如果有"全局"(进程)锁使用,如果可能创建更多的全局锁(如果是这种情况)(对于监视器组)以及对象发生了什么被传递给锁(它们似乎不会引入额外的内存开销).
澄清一下我没有问的问题:我不是在问这个监视器是什么(我以前在大学做了一个).我也没有问如何使用lock,监控,他们如何编译到try/finally等; 我非常清楚这一点(还有其他与之相关的问题).这是关于内部运作的Monitor.Enter和Monitor.Exit.
例如,考虑由十个线程执行的代码:
for (int i=0; i<1000; ++i)
{
lock (myArray[i])
{
// ...
}
}
Run Code Online (Sandbox Code Playgroud)
上下文
基本上,我需要有const void *const一个成员函数,因为这将被传递到第三方库(这意味着我不能使用bind,function等等).由于这似乎是不可能的,我想做下一个最好的事情并将成员函数映射到静态转发方法,然后我可以获取指针(this作为第一个参数传递).
题
我有很多需要注册的函数,具有不同的签名,所以我想有一个很好的解决方案,允许我将成员函数的签名转换为静态方法签名(this当然作为参数传递) -然后,我可以投入到const void* const.所以基本上我想做这样的事情:
所以基本上:
struct Foo
{
MyType Bar(int a);
};
template <typename Ret, typename This, Ret(This::*Func)()>
struct CallWrap0
{
static Ret &&Call(This* thisPtr)
{
return thisPtr->(*Func)();
}
};
int Main()
{
const void * const memberFunction = &(CallWrap0<MyType, Foo, Foo::Bar>()::Call);
// etc.
}
Run Code Online (Sandbox Code Playgroud)
这个解决方案的问题在于 - 尽管它有效 - 但它不是很好,因为我必须明确地告诉编译器类型.我正在寻找一种解决方案,编译器可以自动填充所有管道.
我一直试图用辅助函数解决这个问题,到目前为止没有运气:
template <class Ret, class T, class... Args>
const void* const …Run Code Online (Sandbox Code Playgroud) 假设我有一个如下课程:
public class AcceptMethods
{
public int Accept(string s, int k = 1)
{
return 1;
}
public int Accept(object s)
{
return 2;
}
public int Accept(IEnumerable<object> s)
{
return 7;
}
public int Accept(IList<object> s)
{
return 4;
}
}
Run Code Online (Sandbox Code Playgroud)
现在,如果我尝试在代码中使用它,我将使用如下代码:
object[] list = new object[] { "a", new object[0], "c", "d" };
Assert.AreEqual(7, list.Select((a)=>((int)new AcceptMethods().Accept((dynamic)a))).Sum());
Run Code Online (Sandbox Code Playgroud)
究其原因,它的7,是因为重载喜欢[ IList<object>]在[ IEnumerable<object>]和[ object],因为[ string,int=default]具有优先于[ object]。
在我的场景中,我想使用反射获得最佳的匹配重载。换句话说:“最佳”定义为“ c#重载分辨率”。例如:
int sum = 0;
foreach (var item …Run Code Online (Sandbox Code Playgroud) 虽然使用 goto进行翻译很容易(如f.ex.IL所示),但我想知道是否也可以使用更高级别的表达式和语句来消除所有 goto语句 - 比如说 - 使用Java支持的所有内容.
或者如果您愿意:我正在寻找的是"重写规则",无论创建goto的方式如何,它都将始终有效.
它主要是作为一个理论问题,纯粹是作为利益; 不是好/坏的做法.
我想到的显而易见的解决方案是使用这样的东西:
while (true)
{
switch (state) {
case [label]: // here's where all your goto's will be
state = [label];
continue;
default:
// here's the rest of the program.
}
}
Run Code Online (Sandbox Code Playgroud)
虽然这可能会起作用并且确实符合我的"正式"问题,但我不喜欢我的解决方案.对于其中一个,它已经死了,而且对于两个,它基本上将goto包装成一个与goto完全相同的开关.
那么,有更好的解决方案吗?
更新1
由于很多人似乎认为这个问题"过于宽泛",我将详细说明......我之所以提到Java,是因为Java没有'goto'语句.作为我的一个业余爱好项目,我试图将C#代码转换为Java,这被证明是非常具有挑战性的(部分原因是Java中的这种限制).
这让我思考.如果你有f.ex. 在Open寻址中实现'remove'方法(参见:http://en.wikipedia.org/wiki/Open_addressing-注1),在特殊情况下使用'goto'非常方便,尽管在这个特殊情况下你可以通过引入一个'state'变量来重写它.请注意,这只是一个例子,我已经为连续实现了代码生成器,当你试图对它们进行反编译时会生成大量的goto.
我也不确定在这个问题上的重写是否总是会消除'goto'语句,如果在每种情况下都允许的话.虽然我不是在寻找正式的"证据",但有些证据表明在这个问题上可以消除这种证据会很棒.
所以关于'广泛性',我挑战所有认为有'太多答案'或'很多方法重写goto'以提供算法或方法重写一般情况的人,因为我发现的唯一答案到目前为止我发布的那个.
我正在尝试使用LLVM C API实现一个简单的JIT编译器.到目前为止,我没有生成IR代码并执行它的问题,即:直到我开始处理对象并重新创建它们.
我基本上想做的是在发动机不再使用JIT的资源时清理它们.我基本上试图做的是这样的:
while (true)
{
// Initialize module & builder
InitializeCore(GetGlobalPassRegistry());
module = ModuleCreateWithName(some_unique_name);
builder = CreateBuilder();
// Initialize target & execution engine
InitializeNativeTarget();
engine = CreateExecutionEngineForModule(...);
passmgr = CreateFunctionPassManagerForModule(module);
AddTargetData(GetExecutionEngineTargetData(engine), passmgr);
InitializeFunctionPassManager(passmgr);
// [... my fancy JIT code ...] --** Will give a serious error the second iteration
// Destroy
DisposePassManager(passmgr);
DisposeExecutionEngine(engine);
DisposeBuilder(builder);
// DisposeModule(module); //--> Commented out: Deleted by execution engine
Shutdown();
}
Run Code Online (Sandbox Code Playgroud)
但是,这似乎没有正常工作:循环的第二次迭代我得到一个非常糟糕的错误...
总结一下:破坏和重新创建LLVM API的正确方法是什么?
每次我在IL中使用它们:br_S,ldc_i4_S,ldarg_S等等......所以我只需要问这个问题:
我的意思是......如果你是从IL到本地汇编程序的JIT语言,它在性能方面应该不重要,对吧?那么这些"短手"符号的目的是什么?是仅仅因为IL二进制文件中的字节数较少(例如作为压缩机制)还是有其他原因?
如果它只是一个压缩机制,为什么不使用压缩算法,如deflate?
我只是想知道......假设我在C++中有一个POD结构.如果我愿意放在static_assert那里,它会破坏这是一个POD的事实吗?
我知道我可以很容易地把它放在其他地方,我只是问,因为我感兴趣,如果我应该或不应该这样做......
换句话说(更具体):
#include <iostream>
#include <type_traits>
struct A
{
void* ptr;
static_assert(sizeof(void*) == 8, "Pointer should have size 8; platform unsupported");
};
int main()
{
// Is it guaranteed that this will evaluate to 'true'?
std::cout << std::is_pod<A>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud) 背景
我在这里有一个小服务,其工作方式如下:
appdomain回收后,同样的端口被重新使用。这样,客户端仍然知道要连接到哪个端口。WCF 服务器是基于 TCP 的。
回收
在回收发生之前,appdomain 会进行一些清理。最重要的是,WCF servicehost 已关闭,我希望它会释放 TCP-IP 端口。更详细地:
this.serviceHost.Close();
this.serviceHost = null;
// Some other cleanup
GC.Collect(GC.MaxGeneration);
GC.WaitForFullGCComplete();
GC.WaitForPendingFinalizers();
Run Code Online (Sandbox Code Playgroud)
清理后,appdomain 停止,一秒钟后再次启动。停止应用程序域非常简单:
try
{
System.AppDomain.Unload(this.serviceDomain);
this.serviceDomain = null;
}
catch (CannotUnloadAppDomainException err)
{
Console.WriteLine("Cannot unload app domain (attempt #{1}): {0}", err.Message, i + 1);
Thread.Sleep(TimeSpan.FromSeconds(1.0));
}
catch (AppDomainUnloadedException)
{
this.serviceDomain = null;
}
Run Code Online (Sandbox Code Playgroud)
问题
大多数时候一切正常。但是,每隔几周,回收工作正常,但无法访问 WCF 服务器。错误是:
System.ServiceModel.ProtocolException: You have tried to create a …Run Code Online (Sandbox Code Playgroud) 对于某些项目,我们一直在尝试直接从 Visual Studio 生成代码。基本思想是,您可以创建一堆 ( .foo) 文件,并且每个 ( .foo) 文件对应于一个生成的 ( .foo.cs) 文件。
基本上该过程的工作原理如下:
.foo文件,.foo.cs都会发出一个带有部分类的文件。通常我会为此创建一个文件生成器(自定义工具) - 但是,在这种情况下,我想知道文件名始终是.foo.cs,并且似乎没有办法可以通过单个文件来控制它文件生成器。此外,构建需要来自多个文件的信息这一事实使我选择了另一种方法。
因此,我创建了一个 MS Build Task,并将其注册到 csproj 中:
<UsingTask AssemblyFile="C:\Projects\FooTool\bin\Debug\FooBuildTool.dll"
TaskName="FooBuildTool.FooTool" />
<Target Name="Foo" BeforeTargets="BeforeBuild"
Condition="'$(MSBuildProjectExtension)' == '.csproj'">
<FooTool Language="C#" ProjectFolder="$(ProjectDir)"
ProjectName="$(ProjectName)" Sources="@(Foo)">
<Output ItemName="FooCompile" TaskParameter="ComputedSources" />
</FooTool>
<ItemGroup>
<Compile Include="@(FooCompile->'%(Outputs)')" />
</ItemGroup>
</Target>
Run Code Online (Sandbox Code Playgroud)
从代码生成工作的意义上来说,这工作得很好,并且生成了所有必需的.cs文件。
请注意,如果智能感知在我单击“构建”之前不起作用 - 也没关系。
现在的问题是文件的智能感知已损坏.foo.cs,我正在寻找解决此问题的方法。
我尝试通过.csproj更多更改文件来解决此问题:
<Compile …Run Code Online (Sandbox Code Playgroud) 在调查IsEmpty时,我在MSDN上注意到了这一点:
但是,由于此集合旨在同时访问,因此可能是另一个线程将在IsEmpty返回后修改集合,从而使结果无效.
当然这是真的,但这是否也意味着ConcurrentQueue在检查队列是否为空时不使用读屏障?
我希望有一段代码,如果并发队列为空,则检查另一个线程.像这样的东西:
while (!queue.IsEmpty)
{
}
Run Code Online (Sandbox Code Playgroud)
但是..如果ConcurrentQueue不使用读屏障,我会说我们需要添加自己的内存屏障,以确保我们读取正确的数据,如下所示:
Thread.MemoryBarrier();
while (!queue.IsEmpty)
{
Thread.MemoryBarrier();
}
Run Code Online (Sandbox Code Playgroud)
(顺便说一句:这只是举例说明案例的最小例子,现实中有更多代码).
我的观察是否正确?或者ConcurrentQueue是否处理这个并且第一个实现是否有效?(例如,我对'并发'的期望是什么)?
那么'伯爵'怎么样?我在MSDN上找不到答案......同样的故事?
对于我的一个项目,我使用了很多分支。思考:
if (foo) { do something }
else if (bar) { do something }
else if (bar2) { do something }
... and so on
Run Code Online (Sandbox Code Playgroud)
和
if (foo) { do something }
if (bar) { do something }
if (bar2) { do something }
... and so on
Run Code Online (Sandbox Code Playgroud)
我一直想知道的是,做子表达式和/或逻辑消除来加速它是否有意义。为了完整起见,您可以假设所有这些都在一个函数中。比如说,如果foo和bar有一个共同的子表达式,你可以这样写:
if (commonSubExpr)
{
if (foo without commonSubExpr) { do something }
if (bar without commonSubExpr) { do something }
}
if (bar2) { do something }
... …Run Code Online (Sandbox Code Playgroud)