我已经研究了一下,似乎常识认为结构应该在16字节以下,否则它们会导致复制的性能损失.使用C#7和ref返回,完全避免完全避免复制结构变得非常容易.我假设随着结构大小变小,通过ref传递更多的开销只是复制值.
是否有一个经验法则,关于何时通过值传递结构比通过ref更快?哪些因素会影响这个?(结构大小,过程位数等)
更多上下文:我正在开发一款游戏,绝大多数数据都表示为连续的结构数组,以实现最大的缓存友好性.正如您可能想象的那样,在这种情况下传递结构很常见.我知道分析是确定某些内容的性能影响的唯一真正方法.但是,我想了解它背后的理论概念,并希望在编写代码时考虑到这种理解,并仅描述边缘情况.
此外,请注意,我不会询问最佳做法或通过参考传递一切的理智.我知道"最佳实践"和含义,我故意选择不遵循它们.
按值传递vs传递参考性能C#.net - 此问题讨论通过ref传递引用类型,这与我要求的完全不同.
在.Net中,出于性能原因,我是否应该通过引用传递结构? - 第二个问题涉及到主题,但它是关于结构的特定大小.
要回答Eric Lippert的文章中提出的问题:
你真的需要回答这个问题吗?是的,我愿意.因为它会影响我编写大量代码的方式.
这真的是瓶颈吗?可能不是.但我仍然想知道,因为99%的程序是数据访问模式.在我看来,这类似于选择正确的数据结构.
差异是否相关?它是.通过ref传递大型结构更快.我只是想了解这个的局限性.
你说的这个"更快"是什么?与为同一任务减少CPU工作量相同.
你在看大局吗?是.如前所述,它影响我如何写整个事情.
你为什么甚至问我?因为SO应该是一个Q&A网站.
我知道我可以测量很多不同的组合.这告诉我什么?在我的[.NET版本,进程位,操作系统,CPU]的组合中,X比Y更快.Linux怎么样?Android怎么样?iOS怎么样?我应该对所有可能的硬件/软件组合的所有排列进行基准测试吗?
我认为这不是一个可行的策略.因此,我在这里问一下,对CLR/JIT/ASM/CPU有很多了解的人可以告诉我它是如何工作的,这样我就可以在编写代码时做出明智的决定.
我正在寻找的答案类似于前面提到的结构大小的16字节指南,并解释了原因.
我正在尝试新的C#7功能,我发现了一些奇怪的东西.鉴于以下简化方案:
public struct Command
{
}
public class CommandBuffer
{
private Command[] commands = new Command[1024];
private int count;
public ref Command GetNextCommand()
{
return ref commands[count++];
}
public ref Command GetNextCommand(out int index)
{
index = count++;
return ref commands[index];
}
}
public class BufferWrapper
{
private CommandBuffer cb = new CommandBuffer();
// this compiles fine
public ref Command CreateCommand()
{
ref Command cmd = ref cb.GetNextCommand();
return ref cmd;
}
// doesn't compile
public ref Command CreateCommandWithIndex()
{ …Run Code Online (Sandbox Code Playgroud) 我偶然发现了一个问题,我需要在其静态构造函数中使用该类的实例.我认为不可能这样做,所以我尝试了以下方法:
class Program
{
static void Main(string[] args)
{
Console.WriteLine(Foo.someString);
Console.ReadLine();
}
}
class Foo
{
public static readonly string someString;
static Foo()
{
someString = new Foo().CreateString();
}
private string CreateString()
{
return "some text";
}
}
Run Code Online (Sandbox Code Playgroud)
令我惊讶的是,它的工作原理 - 输出是"一些文本".我相信静态构造函数必须在创建类的实例之前运行并完成.这个答案表明情况不一定如此.这是否意味着静态和实例构造函数彼此独立?最后,这样做是否安全(在静态构造函数中创建实例)?
ps让我们忽略这样一个事实,即可以通过使用不同的方法来避免这种情况.
我正在尝试使用linq和泛型.现在,我刚刚实现了一个GetAll方法,它返回给定类型的所有记录.
class BaseBL<T> where T : class
{
public IList<T> GetAll()
{
using (TestObjectContext entities = new TestObjectContext(...))
{
var result = from obj in entities.CreateObjectSet<T>() select obj;
return result.ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
这很好用.接下来,我想预编译查询:
class BaseBL<T> where T : class
{
private readonly Func<ObjectContext, IQueryable<T>> cqGetAll =
CompiledQuery.Compile<ObjectContext, IQueryable<T>>(
(ctx) => from obj in ctx.CreateObjectSet<T>() select obj);
public IList<T> GetAll()
{
using (TestObjectContext entities = new TestObjectContext(...))
{
var result = cqGetAll.Invoke(entities);
return result.ToList();
}
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我得到以下内容:
base {System.Exception} …Run Code Online (Sandbox Code Playgroud) 我正在开发一个性能非常重要的项目,我想永久禁用AutoEventWireup.问题在于页面和控制指令覆盖了web.config中的设置.由于此项目中将有许多协作者,因此在创建新页面和控件时不可能期望每个人都禁用它(默认情况下这是真的).有可能以某种方式执行这条规则吗?
我希望以与我对ViewState类似的方式解决这个问题 - 在所有新页面继承的基页中以编程方式将EnableViewState设置为false.但似乎没有AutoEventWireup的等价物.
是否可以根据运行时可用的信息将变量转换为另一种类型?
如果我有:
interface Foo
{
}
class Bar implements Foo
{
public function new()
{
}
}
Run Code Online (Sandbox Code Playgroud)
我想做这样的事情(方法是为了清晰简化):
public static function dynamicCast<T : Foo>(target : Foo, cls : Class<T>) : T
{
var ret : T = cast(pTarget, cls);
return ret;
}
Run Code Online (Sandbox Code Playgroud)
我得到以下编译器错误:
Unexpected )
Run Code Online (Sandbox Code Playgroud) 我正在尝试异步等待,但遇到了不应该发生的 UI 阻塞。
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
LoadButton.Click += LoadButton_OnClick;
}
private async void LoadButton_OnClick(object sender, RoutedEventArgs e)
{
LoadButton.IsEnabled = false;
// await Task.Delay(2000);
using(TestContext ctx = new TestContext())
{
IList<User> users = await ctx.Users.ToListAsync();
}
LoadButton.IsEnabled = true;
}
}
Run Code Online (Sandbox Code Playgroud)
如果我注释 DbContext 位并取消注释 Task.Delay,它会按预期运行 - 不阻塞 UI。
根据我的理解,仍然从 UI 线程调用 ToListAsync() 方法,但不应阻止它。即使该方法受 CPU 限制(可能不是),它也会导致延迟,而不是一个完整的块。
我的问题:
我理解正确吗?
为什么我的 UI 在等待 ToListAsync() 时阻塞?
编辑
我尝试在调用此方法之前进行数据库调用以预热所有内容并确保它不会阻止建立第一个连接。我还尝试向 DbSet 添加几千个条目并等待 SaveChangesAsync 并且发生了同样的事情 - UI 完全冻结了几秒钟。
编辑 …
有一个类似这样的配置:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(x =>
{
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(Convert.FromBase64String(config.JwtSecret)),
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
});
Run Code Online (Sandbox Code Playgroud)
是否有在运行时更改 IssuerSigningKey 的正确方法?
想到的想法:
保留对 TokenValidationParameters 的引用,只需替换 IssuerSigningKey
扩展 SymmetricSecurityKey 并执行与上一点类似的操作
这两种方式似乎都太hacky了。我认为有某种机制可以以正确的方式实现这一点,我只是找不到它。
空花括号约束意味着什么?例如(取自Map 的ObjectMap实现):
extern class ObjectMap < K: { }, V > implements Map.IMap<K,V> {
...
Run Code Online (Sandbox Code Playgroud) c# ×5
generics ×2
haxe ×2
ref ×2
asp.net ×1
asp.net-core ×1
async-await ×1
c#-7.0 ×1
dynamic-cast ×1
jwt ×1
performance ×1
struct ×1
wpf ×1