我想实现一个 CoreLocal 映射,它就像 ThreadLocal 一样工作,只是它返回一个特定于当前线程正在运行的核心的值。
这样做的原因是我想编写将从队列中获取作业的代码,但我想优先考虑其关联数据已经在与从队列中选择作业的线程相同的 L1 缓存中的作业. 因此,我不想为整个程序设置一个作业队列,而是希望为每个内核设置一个队列,并且只有当队列为空时,工作线程才会查看其他内核的队列。
我想实现一个 CoreLocal 映射,它就像 ThreadLocal 一样工作,只是它返回一个特定于当前线程正在运行的核心的值。
这样做的原因是我想编写将从队列中获取作业的代码,但我想优先考虑其关联数据已经在与从队列中选择作业的线程相同的 L1 缓存中的作业. 因此,我不想为整个程序设置一个作业队列,而是希望为每个内核设置一个队列,并且只有当队列为空时,工作线程才会查看其他内核的队列。
我不认为有任何调用来获取当前在 JDK 中公开的 CPU,尽管它肯定已经在之前讨论过1并被提议作为 JDK 增强。
我认为,在实现类似的东西之前,最好的选择是使用JNA(最简单)或JNI(快速)之类的东西来包装本地系统调用,例如getcpu
在 Linux 或GetCurrentProcessorNumber
Windows 上。
至少在 Linux 上,getcpu
是在没有内核转换的 VDSO 中实现的,所以它应该只需要几纳秒,再加上 JNI 调用的几纳秒。JNA 比较慢。
如果你真的需要速度,你总是可以将这个函数添加为定制 JVM 的内在函数(因为 OpenJDK 是开源的)。这将减少几纳秒。
请记住,一旦您获得此信息,它可能已经过时,因此您永远不应该依赖它的正确性,只依赖性能。由于您已经需要处理获取“错误”值,另一种可能的方法是将 CPU ID 的缓存值存储在 a 中ThreadLocal
,并且只定期更新它。这使得诸如解析/proc
文件系统之类的缓慢方法变得可行,因为您很少这样做。为了获得最大速度,您可以从计时器线程定期使本地线程无效,而不是在每次调用时检查无效条件。
1强烈推荐阅读讨论和增强请求。
有一个相关的linux 问题没有令人满意的答案(解析top
输出不计算在内,接受的答案不再起作用)。我以为
/proc/<pid>/task/<tid>/sched
可能会在一行中给出这些信息
current_node=0, numa_group_id=0
但是在我运行 4.4.0-92-generic 内核的 i5-2400 上,这条线对于所有线程总是相同的。我想,“节点”是指整个 CPU(套接字),而我只有一个。
我找不到这方面的文档,或者在这个文档中错过了它。
但是,恐怕获得此信息可能无法帮助您:
ThreadLocal
_ CoreLocal
_ someCoreLocalField++
暂停它也会这样做。因此,您需要一些原子或线程局部变量才能使其正常工作,这又可能使其速度太慢而无法满足您的要求。也许你可以检查/proc/[pid]/status
这些字段可能会有所帮助:
cpus_allowed:可以运行此进程的 CPU 掩码
cpus_allowed_list:与之前相同,但采用“列表格式”