Docker不做虚拟化内核,对.NET有什么影响?

news2024/10/3 2:18:56

引子

前两天刷抖音,看见了这样一个问题。

问题:容器化不做虚拟内核,会有什么弊端?Java很多方法会跟CPU的核数有关,这个时候调用系统函数,读到的是宿主机信息,而不是我们限制资源的大小。

思考:在我们.NET中是否也会出现这种问题呢?

环境准备

1. 准备程序

在我们.NET中,并行编程(Parallel)或者线程池(ThreedPool)中,默认会根据CPU数量对我们进行线程分配。

于是我就从Parallel中,找到TaskReplicator类(该类主要用于同时在一个或多个Task中运行委托)下的GenerateCooperativeMultitaskingTaskTimeout方法。

privatestaticintGenerateCooperativeMultitaskingTaskTimeout()
{
    // This logic ensures that we have a diversity of timeouts across worker tasks (100, 150, 200, 250, 100, etc)// Otherwise all worker will try to timeout at precisely the same point, which is bad if the work is just about to finish.int period = Environment.ProcessorCount;
    int pseudoRnd = Environment.TickCount;
    return CooperativeMultitaskingTaskTimeout_Min + (pseudoRnd % period) * CooperativeMultitaskingTaskTimeout_Increment;
}

抽取获取处理器数量方法Environment.ProcessorCount,放到控制台中。

internalclassProgram
{
    staticvoidMain(string[] args)
    {
        Console.WriteLine("获取宿主机器处理器数量:"+Environment.ProcessorCount);
        Console.ReadLine();
    }
}

2. 环境准备

  1. 本机CPU--6个

  1. 虚拟机分配CPU--4个

  1. Docker分配CPU--1个

测试结果

程序最终获取CPU数量是虚拟机的数量

采用cpus结果:

采用–cpuset-cpus命令结果:

Docker和虚拟机的区别:

2.分析需求

  • put数据时:

  • key值hash后的索引处没有元素,需要创建链表头节点,放到该位置的数组空间里。

  • key值hash后的索引处有元素,说明产生Hash碰撞,需要在链表中结尾处挂载节点,如果在遍历链表的过程中,发现了同key的数据,则执行覆盖即可,不再继续往下遍历去挂载新节点。

  • 假设数组使用的空间超过了总长度的75%,那么对数组进行扩容。先创建新数组,把旧数据写到新数组中(此时需要重新根据key计算Hash,因为数据长度变化了,影响计算结果了),在用新数据替换掉原来的旧数组。

  • get数据时:

  • key值hash后的索引下标处的元素为空的话,则不存在数据。

  • key值hash后的索引下标处存在链表的话,需要遍历链表,找到key相对应的value值。

3.代码实现

  • Node类实现

package com.zaevn.hashmap;

/**
 * @author: zae
 * @date: 2023/1/30
 * @time: 11:25
 */publicclassNode {

    String key;
    String value;
    Node next;

    publicNode(String key, String value, Node nextNode) {
        this.key = key;
        this.value = value;
        this.next = nextNode;
    }
}
  • LinkNode类实现

package com.zaevn.hashmap;

/**
 * @author: zae
 * @date: 2023/1/30
 * @time: 11:27
 */publicclassListNode {
    // 头节点
    Node head;

    /**
     * 添加数据,挂载链表的节点
     * @param key
     * @param value
     */publicvoidaddNode(String key,String value){
        // 如果头节点是空,则结束if(head == null ){return;}

        // 如果头节点不为空,则往下挂载节点Nodenode=newNode(key,value,null);
        Nodetemp= head;
        while(true){
            // 遇到相同的key,覆盖数据if(key.equals(temp.key)){
                temp.value = value;
                return;
            }

            if(temp.next == null){
                break;
            }
            temp = temp.next;
        }
        // 循环结束后则挂上数据
        temp.next = node;
    }

    /**
     * 获取数据
     * @param key
     * @return
     */public String getNode(String key){
        if(head == null ){returnnull;}

        Nodetemp= head;
        while(true){
            if(key.equals(temp.key)){
                return temp.value;
            }
            if(temp.next == null){
                break;
            }
            temp = temp.next;
        }
        returnnull;
    }
}
  • MyHashMap类实现

package com.zaevn.hashmap;

/**
 * @author: zae
 * @date: 2023/1/30
 * @time: 11:27
 */publicclassMyHashMap {
    // 数组初始化:2的n次方
    ListNode[] map = newListNode[8];
    // ListNode的个数int size;

    // 由于扩容时是先创建一个新数组,因此先声明出来
    ListNode[] mapNew;
    int sizeNew;

    /**
     * put方法
     * @param key
     * @param value
     */publicvoidput(String key,String value){
        if(size>map.length * 0.75){
            System.out.println("开始进行扩容,当前size="+size+",数组长度为:"+map.length);
            doExtendMap();
            System.out.println("扩容结束,当前size="+size+",数组长度为:"+map.length);
        }

        // 1.对key进行hash算法然后取模intindex= Math.abs(key.hashCode())%map.length;

        ListNodelistNode= map[index];
        // 如果索引位置的元素为空,则新加一个元素(创建头节点)if(listNode == null){
            ListNodelistNodeNew=newListNode();
            Nodenode=newNode(key,value,null);
            listNodeNew.head = node;
            map[index] = listNodeNew;
            size ++;
        }else{
            // 如果索引位置的元素不为空,则往链表中挂载数据
           listNode.addNode(key,value);
        }
    }

    public String get(String key){
        // 1.对key进行hash算法然后取模intindex= Math.abs(key.hashCode())%map.length;

        if(map[index] == null){
            returnnull;
        }else{
            return map[index].getNode(key);
        }
    }

    /**
     * 达到阈值后开始进行扩容
     */publicvoiddoExtendMap(){
        sizeNew = 0;
        // 1.先创建一个新的数组,长度为原来的二倍
        mapNew = newListNode[map.length * 2];

        // 2.将旧数据映射到新的数组上(因为数组长度变化,因此hash规则变化,所有的值需要重新计算hash值)for(inti=0;i<map.length;i++){
            ListNodelistNode= map[i];
            if(listNode == null){
                continue;
            }
            Nodetemp= listNode.head;
            while (true){
                doPutData(mapNew,temp.key,temp.value);
                if(temp.next == null){
                    break;
                }
                temp = temp.next;
            }
        }

        // 3.将新的数组替换旧的数组
        map = mapNew;
        this.size = sizeNew;
    }

    privatevoiddoPutData(ListNode[] mapParam,String key,String value){
        intindex= Math.abs(key.hashCode())%mapParam.length;
        ListNodelistNode= mapParam[index];
        if(listNode == null){
            ListNodelistNodeNew=newListNode();
            Nodenode=newNode(key,value,null);
            listNodeNew.head = node;
            mapParam[index] = listNodeNew;
            sizeNew ++;
        }else{
            listNode.addNode(key,value);
        }
    }

    publicstaticvoidmain(String[] args) {
        // 1、一般校验
        MyHashMap hashMap0=newMyHashMap();
        hashMap0.put("key1","value1");
        System.out.println("一般校验:"+hashMap0.get("key1"));
        System.out.println("--------------------------------------------");


        // 2、同key覆盖校验
        MyHashMap hashMap1=newMyHashMap();
        hashMap1.put("key2","value00");
        hashMap1.put("key2","value01");
        System.out.println("同key覆盖校验:"+hashMap1.get("key2"));
        System.out.println("--------------------------------------------");

        // 3、哈希碰撞校验(k1和k9的经过哈希计算后得到的索引都是6)
        MyHashMap hashMap2=newMyHashMap();
        hashMap2.put("k1","value_k1");
        hashMap2.put("k9","value_k9");
        System.out.println("哈希碰撞校验:k1:"+hashMap2.get("k1")+"  k9:"+hashMap2.get("k9"));
        System.out.println("--------------------------------------------");


        // 4、扩容校验
        MyHashMap hashMap3=newMyHashMap();
        hashMap3.put("m3","cccccc");
        hashMap3.put("c1","kkkkkk");
        hashMap3.put("c2","mmmmmmm");
        hashMap3.put("b1","bbbbbbb");
        hashMap3.put("m1","cccccc");
        hashMap3.put("c3","kkkkkk");
        hashMap3.put("c4","mmmmmmm");
        hashMap3.put("b2","bbbbbbb");
        hashMap3.put("m2","cccccc");
        hashMap3.put("c5","kkkkkk");
        hashMap3.put("c6","mmmmmmm");
        hashMap3.put("b3","bbbbbbb");
        System.out.println("扩容后的c4:"+hashMap3.get("c4"));
        System.out.println("扩容后的b3:"+hashMap3.get("b3"));
    }

}

3.运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/337689.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FoveaBox原理与代码解析

paper&#xff1a;FoveaBox: Beyond Anchor-based Object Detectorcode&#xff1a;https://github.com/taokong/FoveaBox背景基于anchor的检测模型需要仔细设计anchor&#xff0c;常用方法之一是根据特定数据集的统计结果确定anchor的number、scale、ratio等&#xff0c;但这种…

elasticsearch8.3.2搭建部署

Elasticsearch8.3.2搭建部署详细步骤 0.过往文章 ES-6文章&#xff1a; Elasticsearch6.6.0部署、原理和使用介绍: https://blog.csdn.net/wt334502157/article/details/119515730 ES-7文章&#xff1a; Elasticsearch7.6.1部署、原理和使用介绍: https://blog.csdn.net/wt…

堆排序

章节目录&#xff1a;一、相关概述1.1 基本介绍1.2 排序思想二、基本应用2.1 步骤说明2.2 代码示例三、结束语一、相关概述 1.1 基本介绍 堆排序是利用堆这种数据结构而设计的一种排序算法&#xff0c;堆排序是一种选择排序。它的最坏最好平均时间复杂度均为 O(nlogn)&#x…

(深度学习快速入门)第五章第二节:GAN变体

文章目录一&#xff1a;CycleGAN&#xff08;1&#xff09;概述&#xff08;2&#xff09;双判别器&#xff08;3&#xff09;损失函数二&#xff1a;StyleGAN&#xff08;1&#xff09;解耦表征学习&#xff08;2&#xff09;概述三&#xff1a;DCGAN一&#xff1a;CycleGAN …

4.5.8 Set接口与HashSet

文章目录1.概述2.Set集合的特点3.常用方法4.HashSet4.1 概述4.2 练习: Set相关测试一4.3 练习: Set相关测试二1.概述 Set是一个不包含重复数据的CollectionSet集合中的数据是无序的(因为Set集合没有下标)Set集合中的元素不可以重复 – 常用来给数据去重 2.Set集合的特点 数据…

排序算法学习

文章目录前言一、直接插入排序算法二、折半插入排序算法三、2路插入排序算法四、快速排序算法学习前言 算法是道路生涯的一个巨大阻碍。今日前来解决这其中之一&#xff1a;有关的排序算法&#xff0c;进行实现以及性能分析。 一、直接插入排序算法 插入排序算法实现主要思想…

Kubernetes_从Linux的cgroup配置到Kubernetes中的cgroup配置

系列文章目录 文章目录系列文章目录前言一、Linux层面的cgroup二、Kubernetes层面的cgroup driver2.1 kubelet和docker的Cgroup Driver不同导致kubelet开启失败2.1.1 命令2.1.2 演示总结前言 一、Linux层面的cgroup cgroup是控制组&#xff0c;用来控制进程对资源的分配&…

Cesium-数字仿真-你总要了解

Cesium&#xff08;专注于时空数据的实时可视化) cesium是一款三维地球开源框架&#xff08;可以多平台、跨平台使用&#xff09;cesium隶属于美国AGI公司&#xff08;Analytical Graphics Incorporation&#xff09;&#xff0c;美国通用公司宇航部的工程师创始开源 周边产…

微信小程序的优化方案之主包与分包的研究

什么是分包&#xff1f; 某些情况下&#xff0c;开发者需要将小程序划分成不同的子包&#xff0c;在构建时打包成不同的分包&#xff0c;用户在使用时按需进行加载。 在构建小程序分包项目时&#xff0c;构建会输出一个或多个分包。每个使用分包小程序必定含有一个主包。所谓的…

错误代码0xc0000001要怎么解决?如何修复错误

出现错误代码0xc0000001这个要怎么解决&#xff1f;其实这个的蓝屏问题还是非常的简单的&#xff0c;有多种方法可以实现 解决方法一 1、首先使用电脑系统自带的修复功能&#xff0c;首先长按开机键强制电脑关机。 注&#xff1a;如果有重要的资料请先提前备份好&#xff0c;…

【C++】C++11 ~ 包装器解析

&#x1f308;欢迎来到C专栏~~包装器解析 (꒪ꇴ꒪(꒪ꇴ꒪ )&#x1f423;,我是Scort目前状态&#xff1a;大三非科班啃C中&#x1f30d;博客主页&#xff1a;张小姐的猫~江湖背景快上车&#x1f698;&#xff0c;握好方向盘跟我有一起打天下嘞&#xff01;送给自己的一句鸡汤&a…

Java 内存结构解密

程序计数器 物理上被称为寄存器&#xff0c;存取速度很快。 作用 记住下一条jvm指令的执行地址。 特点 线程私有&#xff0c;和线程一块出生。 不存在内存溢出。 虚拟机栈 每个线程运行时所需要的内存&#xff0c;称为虚拟机栈。 每个栈由多个栈帧组成&#xff0c;…

C/C++ 中的宏 (macros) 与宏展开的可视化显示

C/C 中的宏 (macros) 与宏展开的可视化显示1. Replacing text macros (替换文本宏) https://en.cppreference.com/w/cpp/preprocessor/replace https://www.codecademy.com/resources/docs/cpp/macros A macro is a label defined in the source code that is replaced by it…

dll修复工具哪个比较好?修复工具介绍

DLL&#xff08;动态链接库&#xff09;是Windows操作系统中非常重要的一部分&#xff0c;它们存储了各种软件应用程序所需的公共代码和数据。然而&#xff0c;随着时间的推移&#xff0c;电脑上的DLL文件可能会因为各种原因而损坏或丢失&#xff0c;导致系统出现错误。因此&am…

PyTorch自定义损失函数实现

在机器学习中&#xff0c;损失函数是衡量预测输出与实际输出之间差异的关键组成部分。 它在模型训练中起着至关重要的作用&#xff0c;因为它通过指示模型应该改进的方向来指导优化过程。 损失函数的选择取决于具体的任务和数据类型。 在本文中&#xff0c;我们将以用于手写数字…

VHDL语言基础-时序逻辑电路-概述

目录 时序逻辑电路-概述: 时序逻辑电路: 时序逻辑电路——有记忆功能: 时序电路的分类: 按照触发器的动作特点: 按照输出信号的特点: 同步时序逻辑电路: 异步时序逻辑电路: 时序逻辑电路-概述: 数字电路按其完成逻辑功能的不同特点&#xff0c;划分为组合逻辑电路和时序…

福利篇1——嵌入式软件行业与公司汇总

前言 汇总嵌入式软件行业与公司,供参考。 文章目录 前言一、嵌入式软件行业和公司汇总1、芯片行业代表性公司2、人工智能代表性公司1)智能驾驶方向代表性公司2)机器人方向代表性公司3、消费电子领域代表性公司4、传统电子电器领域代表性公司5、国企和军工领域代表性公司6、网…

嵌入式系统那些事——aarch64 backtrace嵌入式汇编实现

0 背景 在aarch64嵌入式应用开发中&#xff0c;经常会遇到段错误(segmentation fault)&#xff0c;但是通常情况下系统报错后直接退出&#xff0c;没有异常调用打印信息&#xff0c;定位出错原因十分困难。经确认&#xff0c;该问题是由于没有设置捕获段错误&#xff0c;并调用…

推荐3dMax三维设计十大插件

3dMax是一款功能非常强大的三维设计软件&#xff0c;但无论它的功能多么强大&#xff0c;也不可能包含所有三维方面的功能&#xff0c;这时候&#xff0c;第三方插件可以很好的弥补和增强3dMax的基本功能&#xff0c;下面就给大家介绍十款非常不错的3dMax插件。 森林包&#xf…

Unsupervised Question Answering 简单综述

Unsupervised Question Answering by Cloze Translation, ACL 2019 随机从文本中抽取noun phrases或者named entity作为答案将答案部分mask掉&#xff0c;生成cloze question利用无监督翻译&#xff0c;将cloze question转化为natural question 缺点&#xff1a; 直接利用原句…