首页 > 其他分享 >记录一次性能问题的解决

记录一次性能问题的解决

时间:2024-11-07 12:41:19浏览次数:1  
标签:usec 记录 tv 性能 tdiff 线程 解决 sec void

最近在用schbench测试机器调度性能。测试是绑定在一个socket上进行的。当worker线程数等于socket包含的cpu数时耗时会发生一次跳变。主要是futex wake的时候执行时间变长。开始怀疑是kernel的执行逻辑发生了变化,但查看ftrace后发现没有变化。第二个怀疑点是kernel执行的某个子函数耗时变大,但是使用ebpf工具测量每个子函数的耗时时发现耗时增量与函数执行时间占比成正比,也就是函数是均匀增加的,感觉是硬件问题引发的程序整体变慢。我想既然是程序整体变慢那就跟测试程序无关,我可以在futex函数内加一些自己的测试代码,看看测试代码会不会跟原来的代码一样变慢。结果正如预想的,插入的独立代码也会变慢。这就证明了整个线程被某种神秘力量拉扯导致整体发生了性能下降。那这股神秘力量是什么呢?

通过观察message线程worker线程所在cpu所属的core发现,worker线程已经占据了socket内所有的物理core,message正在与某个worker线程共享一个物理core。所以怀疑点变为共享core导致的性能下降,这也是非常合理的性能下降的情形。

通过缩小测试范围发现,一旦message线程和worker线程共享core就会发生性能下降的问题。可以确定原因了。(为啥没早点发现,这个数字还是有点明显的)

再通过一些自己创建的测试case去模拟两个线程共享一个物理core,测试影响,测试case如下:

#include <pthread.h>
#include <sys/time.h>
#include <stdlib.h>
#include <stdio.h>

void* worker(void*);
void* worker1(void*);

int over = 0;

int main() {
        pthread_t thread0;
        pthread_t thread1;
        void * res0;
        void * res1;

        pthread_create(&thread0, NULL, worker, NULL);
        pthread_create(&thread1, NULL, worker1, NULL);
        pthread_join(thread0, &res0);
        pthread_join(thread1, &res1);

        return 0;

}

void tvsub(struct timeval * tdiff, struct timeval * t1, struct timeval * t0)
{
        tdiff->tv_sec = t1->tv_sec - t0->tv_sec;
        tdiff->tv_usec = t1->tv_usec - t0->tv_usec;
        if (tdiff->tv_usec < 0 && tdiff->tv_sec > 0) {
                tdiff->tv_sec--;
                tdiff->tv_usec += 1000000;
                if (tdiff->tv_usec < 0) {
                        fprintf(stderr, "lat_fs: tvsub shows test time ran backwards!\n");
                        exit(1);
                }
        }

        /* time shouldn't go backwards!!! */
        if (tdiff->tv_usec < 0 || t1->tv_sec < t0->tv_sec) {
                tdiff->tv_sec = 0;
                tdiff->tv_usec = 0;
        }
}

unsigned long long tvdelta(struct timeval *start, struct timeval *stop)
{
        struct timeval td;
        unsigned long long usecs;

        tvsub(&td, stop, start);
        usecs = td.tv_sec;
        usecs *= 1000000;
        usecs += td.tv_usec;
        return (usecs);
}

#define nop __asm__ __volatile__("rep;nop": : :"memory")
static void usec_spin(unsigned long spin_time)
{
        struct timeval now;
        struct timeval start;
        unsigned long long delta;

        if (spin_time == 0)
                return;

        gettimeofday(&start, NULL);
        while (1) {
                gettimeofday(&now, NULL);
                delta = tvdelta(&start, &now);
                if (delta > spin_time)
                        return;
                nop;
        }
}

void* worker(void* __unused) {
        long input = 64;
        long count = 0;
        char addr[64];

        int loop = 100000000, i = 0, start = 2, end = 2;
        while (i++ < loop) {
                for(int k = 0; k < input; k++) {
                        addr[k] = 1;
                        count++;
                }
        }

        over = 1;
}

void* worker1(void* __unused) {
        while(!over){
                usec_spin(30000);
        }
}

一个线程循环访存+自增,表示工作线程,另一个线程循环getime,表示干扰项。当访存循环结束,整个进程结束。

这个例子可以测量到超线程之间的影响,当然不是什么很好的例子,只是可以模拟schbench中遇到的问题。

结论是:运行在同一个物理core中不同超线程的程序之间会有相互的干扰,在core足够多的情况下应该尽量避免这种调度。所以,调度器希望负载均衡不是没有道理,因亲和性而希望imbalance也是有一些平衡点在内的。这是个矛盾,要因测试case而变。

 感悟:

性能问题不像解bug,bug通过缩小测试范围总能得到一个答案,但是性能问题要考虑的维度太多,根本没有一个显而易见的范围,当你将自己限制在某个预设答案范围内时很可能就跟真正的原因错过了。将自己想象成一台计算机,根据了解到的事实在脑海中模拟运行的过程,靠感觉去寻找答案也许是个不错的办法。

标签:usec,记录,tv,性能,tdiff,线程,解决,sec,void
From: https://www.cnblogs.com/banshanjushi/p/18531912

相关文章

  • 实战分享记录一次某商城0元购和SQL注入漏洞详细操作(学会了你也可以轻松实现!)
    文章目录1前言2商城0元购一、支付漏洞简介二、0元购漏洞零元购漏洞测试修复建议3SQL注入漏洞一、影响参数:二、漏洞POC:三、SQL注入漏洞测试四、修复建议4总结......
  • UE5.4 打包 Android, gradle time out下载失败解决办法
     Downloadinghttps://services.gradle.org/distributions/gradle-7.5-all.zip        atjava.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:531)        atjava.base/sun.net.www.http.HttpClient.openServer(HttpClient.java:636) ......
  • win11中使用docker-nacos连接容器中的mysql实例记录
     二.方式11.拉取nacosdockerpullnacos/nacos-server2.在dockerdesktop中进行配置如下图相比较’方式2‘这种方式更简单,mysqlip地址需要使用ipv4地址,具体的自己查看ipconfig的ipv4地址(注意:localhsot/127.0.0.1/容器名称都是不行的)下面这几个参数在application.proper......
  • 找到PMF第一关 - 找个重要问题来解决
    找到PMF(Product-MarketFit产品市场契合度)是创业和产品开发中至关重要的一步,它决定了你的产品能否在市场中取得成功。PostHog的CEOJamesHawkins对此有详细介绍:https://posthog.com/founders/product-market-fit-game他把过程分成五个级别/关卡:找到一个重要的问题来......
  • 第一款让RTX 4090成为瓶颈的处理器!锐龙7 9800X3D首发评测:网游性能断崖式领先
    一、前言:AMD第一款真正全能不偏科的顶级处理器1年前测试锐龙77800X3D的时候,我们曾评价它是20年来最优秀的游戏处理器。毕竟,他拥有无与伦比的游戏性能,但功耗还不到对手同级产品的一半,同时由于不需要高端电源、散热器、主板,大幅度降低了装机成本。但它也有不足之处,尤其是由于存......
  • OCR文字识别 —— 高效精准的智能解决方案,支持私有化部署更安心
    在数字化时代,文字识别技术的重要性日益凸显。无论是企业办公中的文档处理,还是个人生活中的信息提取,都离不开高效准确的文字识别工具。今天,我要向大家介绍一款强大的文字识别软件——OCR文字识别,尤其是其私有化部署的优势,为用户带来全新的体验。一、OCR文字识别的强大功能......
  • 高级SQL技巧:提升数据库性能与查询效率
    索引优化索引类型B树索引:B树索引适用于多种数据库操作,包括等值查询、范围查询和排序。B树索引通过将数据存储在一个平衡树结构中,允许快速的数据访问。B树索引的深度影响查询性能,因此,选择正确的索引列和维护索引的健康状况是至关重要的。例如,对于一个大型的电子商务数据库,对产......
  • .NET 8 高性能跨平台图像处理库 ImageSharp
    阅读目录前言项目介绍项目使用常用方法常用滤镜项目地址总结最后前言传统的System.Drawing库功能丰富,但存在平台限制,不适用于跨平台开发。.NET8的发布,ImageSharp成为了一个更好的选择。ImageSharp是一个完全开源、高性能且跨平台的图像处理库,专为.NET设计......
  • 找到PMF第一关 - 找个重要问题来解决
    找到PMF(Product-MarketFit产品市场契合度)是创业和产品开发中至关重要的一步,它决定了你的产品能否在市场中取得成功。PostHog的CEOJamesHawkins对此有详细介绍:https://posthog.com/founders/product-market-fit-game他把过程分成五个级别/关卡:找到一个重要的问题来......
  • 解决:在表单框内没有值的时候就点击弹窗确认按钮会触发表单校验,但是之后若填了值表单校
      save2(){//在点击确认按钮时,首先清除表单的校验错误this.$refs.formRef2.clearValidate();//重新进行校验this.$refs.formRef2.validate((valid)=>{if(valid){//修改操作if(this.messagetId!==undefined&&this.messagetId......