关于Response.Write一个提高性能的技巧测试

作者在MSDN看到提高输出性能技巧,新建WebForm用C#和Visual Basic进行测试,对比单个和多个Response.Write调用在不同循环次数下的性能。结果显示多个调用性能更高,耗时主要因创建新字符串对象。但测试时间有波动,作者询问更精确测试方法。

今天在看MSDN的时候,看到里面提供了一个技巧, MSDN原文如下:

      该方法提供非常有效的缓冲和连接服务。但是,如果您正在执行广泛的连接,请使用多个 Response.Write 调用。下面示例中显示的技术比用对 Response.Write 方法的单个调用连接字符串更快。
   [C#]
   Response.Write("a");
   Response.Write(myString);
   Response.Write("b");
   Response.Write(myObj.ToString());
   Response.Write("c");
   Response.Write(myString2);
   Response.Write("d");

   [Visual Basic]
   Response.Write("a")
   Response.Write(myString)
   Response.Write("b")
   Response.Write(myObj.ToString())
   Response.Write("c")
   Response.Write(myString2)
   Response.Write("d")

       为了验证一下正确性,我于是新建了一个WebForm,具体的测试代码如下:

       Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim startTime As Long
        Dim endTime As Long
        Dim intI As Integer

        Dim str1 = "Ilovethisgame"
        Dim str2 = "Ihatethisgame"

        startTime = DateTime.Now.Ticks

        For intI = 0 To 100000
            Response.Write("basketball" & str1 & "I can not say that" & str2)
        Next

        endTime = DateTime.Now.Ticks

        Response.Write("<br> Take Time(use only one Response.Write): " & (endTime - startTime) / 10000 & " (ms)")

        startTime = DateTime.Now.Ticks

        For intI = 0 To 100000
            Response.Write("basketball")
            Response.Write(str1)
            Response.Write("I can not say that")
            Response.Write(str2)
        Next

        endTime = DateTime.Now.Ticks

        Response.Write("<br> Take Time(use multi Response.Write): " & (endTime - startTime) / 10000 & " (ms)")
    End Sub

    这里帖出来的是循环100000次的情况,我总共是测试了4个级别的,分别是循环100次,1000次,10000次, 100000次。(再到后面,我的机器就表现为CPU占用100%,我什么事情都干不了了,^_^)

    具体的结果是:

       次数                                         用一个Response.Write输出(ms)                 用多个Response.Write输出(ms)

       100                                                             0                                                                             0

       1000                                                           0                                                                             0

       10000                                                     15.9145                                                                    0

       100000                                                   238.7175                                                               95.487

     我还在这些数据中去了同样级别的其他数据进行测试,同样的数据也测试了多次。虽然数据有波动。但是从总的数据来分析,确实使用多个Response.Write的话性能会高一些。

     想了一下,第一种方法之所以会性能差一些,可能是在字符串进行连接的时候创造新的字符串对象的时候占去的时间。于是将测试代码改造了一下,如下:

    Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        Dim startTime As Long
        Dim endTime As Long
        Dim intI As Integer

        Dim str1 = "Ilovethisgame"
        Dim str2 = "Ihatethisgame"
        Dim strTotal = ""

        startTime = DateTime.Now.Ticks

        For intI = 0 To 10000
            ' 这里是更改的代码部分
            strTotal = strTotal & "basketball"
            strTotal = strTotal & str1
            strTotal = strTotal & "I can not say that"
            strTotal = strTotal & str2
            strTotal = ""
        Next

        endTime = DateTime.Now.Ticks

        Response.Write("<br> Take Time(use only one Response.Write): " & (endTime - startTime) / 10000 & " (ms)")

        startTime = DateTime.Now.Ticks

        For intI = 0 To 10000
            Response.Write("basketball")
            Response.Write(str1)
            Response.Write("I can not say that")
            Response.Write(str2)
        Next

        endTime = DateTime.Now.Ticks

        Response.Write("<br> Take Time(use multi Response.Write): " & (endTime - startTime) / 10000 & " (ms)")
    End Sub

    测试的记录如下:

   次数                                      用一个Response.Write输出(ms)            用多个Response.Write输出(ms)

   100                                                                0                                                                      0

    1000                                                             0                                                                      0

    10000                                                     15.6642                                                               0

    100000                                                   156.642                                                          78.321      

    从上面的数据可以看出占用时间数量级是一样的     

     仔细想了一下,这回测试收获是:

          1. 知道了一个提高输出性能的方法。

          2. 耗时主要是由于不断的new 出新的字符串对象造成的。

       但是也有一些迷惑:

           1. 测试过程中,有时候发现测试的时间波动还是比较大的,虽然没有数量级的变化。比如可能第一次测试得到的数据是156.642 ms,下次可能有220.780 ms等等。不知道是不是跟当时的CPU使用率有关。

           2. 如果上面的假设成立,那么有没有更好,更精确的测试方法和思路呢?

      

      那么就请各位看官赐教了!谢谢 (还有对上面的测试思路有指正的也请不惜赐教)

# -*- coding: utf-8 -*- # ================== Python模块导入在测试中的应用 ================== # 本课程专为测试工程师设计,讲解模块导入机制及在接口测试中的实际应用 # 每行代码均有详细中文注释,确保学习效果 # ================== 第一部分:总览 - 测试中模块导入核心概念 ================== """ 📚 模块导入在测试中的重要性 1. 代码组织:将测试代码模块化,提高可维护性 2. 复用共享:避免重复代码,提高测试开发效率 3. 环境隔离:分离测试环境配置和生产环境配置 4. 资源管理:集中管理测试数据、工具函数和配置 🔍 测试工程师必备模块: 1. requests - HTTP接口测试 2. pytest - 测试框架 3. json/csv - 测试数据处理 4. logging - 测试日志记录 5. os/sys - 系统/环境操作 """ # ================== 第二部分:分述 - 测试专用模块导入详解 ================== # === 基础导入方式在测试中的应用 === """ 🔧 三种基础导入方式: 1. import 模块名 → 导入整个模块(适合频繁使用) 2. from 模块 import 名称 → 导入特定功能(减少内存占用) 3. import 模块 as 别名 → 简化长模块名称(提高代码可读性) """ # === 示例1:requests库在接口测试中的基础导入 === import requests # 导入整个requests模块用于HTTP请求 def test_api_health_check(): """API健康检查测试(Windows环境适用)""" response = requests.get("https://jsonplaceholder.typicode.com/health") # 发送GET请求 assert response.status_code == 200 # 断言状态码 print(f"✅ API健康检查通过,响应时间: {response.elapsed.total_seconds():.2f}秒") # 打印响应时间 # === 新增:requests库详细用法示例 === def demonstrate_requests_features(): """展示requests库在接口测试中的完整功能(Windows环境适用)""" print("\n" + "=" * 50) print("📡 REQUESTS库详细用法演示") print("=" * 50) # === 1. GET请求参数传递详解 === print("\n🔍 GET请求参数传递:") # 基础GET请求 base_response = requests.get("https://jsonplaceholder.typicode.com/posts") print(f"基础GET请求状态码: {base_response.status_code}, 获取数据量: {len(base_response.json())}") # 带查询参数的GET请求(推荐方式) params = { "userId": 1, "_limit": 3 # 限制返回结果数量 } param_response = requests.get( "https://jsonplaceholder.typicode.com/posts", params=params ) print(f"带参数GET请求实际URL: {param_response.request.url}") print(f"获取到 {len(param_response.json())} 条用户数据") # === 2. POST请求参数传递详解 === print("\n📤 POST请求参数传递:") # 表单格式提交(application/x-www-form-urlencoded) form_data = { "title": "测试表单提交", "body": "这是通过表单提交的内容", "userId": 1 } form_response = requests.post( "https://jsonplaceholder.typicode.com/posts", data=form_data, # 关键参数:data headers={"Content-Type": "application/x-www-form-urlencoded"} ) print(f"表单提交状态码: {form_response.status_code}, 响应ID: {form_response.json().get('id')}") # JSON格式提交(application/json) json_payload = { "title": "测试JSON提交", "body": "这是通过JSON提交的内容", "userId": 1, "tags": ["测试", "API"], "meta": {"source": "Windows", "version": 1.2} } json_response = requests.post( "https://jsonplaceholder.typicode.com/posts", json=json_payload, # 关键参数:json(自动设置Content-Type) timeout=5 # 添加超时控制 ) print(f"JSON提交状态码: {json_response.status_code}, 响应ID: {json_response.json().get('id')}") # 文件上传(multipart/form-data) try: # 创建测试文件 with open("test_upload.txt", "w", encoding="utf-8") as f: f.write("这是测试上传的文件内容") files = {'file': open('test_upload.txt', 'rb')} file_response = requests.post( "https://httpbin.org/post", # 使用测试服务 files=files ) print(f"文件上传状态码: {file_response.status_code}") print(f"上传文件名: {file_response.json()['files']['file']}") except Exception as e: print(f"文件上传测试失败: {str(e)}") # === 3. 带认证的请求 === print("\n🔐 带认证的请求:") auth_response = requests.get( "https://jsonplaceholder.typicode.com/users/1", auth=("testuser", "Test123!") # 基础认证 ) print(f"认证请求状态码: {auth_response.status_code}") # === 4. 处理响应内容 === print("\n📥 响应内容处理:") response = requests.get("https://jsonplaceholder.typicode.com/comments/1") # 响应头信息 print(f"响应头 - Content-Type: {response.headers['Content-Type']}") # JSON响应处理 json_data = response.json() print(f"JSON数据 - 邮箱: {json_data['email']}") # 二进制响应处理 image_response = requests.get("https://picsum.photos/100/100") print(f"图片响应 - 大小: {len(image_response.content)} bytes") print("\n✅ REQUESTS库功能演示完成") # === 示例2:精准导入在测试数据生成中的应用 === from faker import Faker # 仅导入Faker类用于测试数据生成 def generate_test_data(num_records=5): """生成测试用户数据(Windows环境适用)""" fake = Faker() # 创建Faker实例 return [ { "id": i + 1, "name": fake.name(), # 生成随机姓名 "email": fake.email(), # 生成随机邮箱 "created_at": fake.date_time_this_year().isoformat() # 生成创建时间 } for i in range(num_records) ] # === 示例3:别名导入在测试报告中的应用 === import pandas as pd # 导入pandas并设置别名pd def create_test_report(test_results): """创建测试报告(Windows环境适用)""" # 测试结果转换为DataFrame df = pd.DataFrame(test_results) # 计算通过率 pass_rate = df[df['status'] == 'PASS'].shape[0] / df.shape[0] * 100 # 添加总结行 summary = pd.DataFrame([{ 'test_case': 'SUMMARY', 'status': f'Pass Rate: {pass_rate:.1f}%', 'duration': f'Total: {df["duration"].sum():.2f}s' }]) # 合并报告 report_df = pd.concat([df, summary], ignore_index=True) # 保存报告 report_df.to_excel("test_report.xlsx", index=False) print("✅ 测试报告已保存到 test_report.xlsx") # === 高级导入技巧测试中的实践 === # === 示例4:条件导入在跨环境测试中的应用 === import os # 导入操作系统模块 # 根据环境变量导入不同配置 if os.getenv("TEST_ENV") == "production": from config.prod_settings import API_URL, API_KEY # 生产环境配置 print("⚠️ 使用生产环境配置 - 谨慎操作!") else: from config.test_settings import API_URL, API_KEY # 测试环境配置 print("✅ 使用测试环境配置") def test_protected_endpoint(): """测试需要认证的API端点(Windows环境适用)""" headers = {"Authorization": f"Bearer {API_KEY}"} response = requests.get(f"{API_URL}/protected", headers=headers) assert response.status_code == 200 print("✅ 受保护端点测试通过") # === 示例5:延迟导入在性能敏感测试中的应用 === def run_performance_test(): """执行性能测试(仅在需要时导入资源密集型模块)""" # 模拟前置操作 print("准备性能测试环境...") # 延迟导入 import numpy as np # 仅在需要时导入 # 创建大型测试数据集 large_data = np.random.rand(10000, 100) print(f"✅ 已创建测试数据集: {large_data.shape[0]}行 x {large_data.shape[1]}列") # 模拟性能测试 result = np.mean(large_data, axis=0) print(f"性能测试完成,结果维度: {result.shape}") # === 示例6:相对导入在测试框架中的应用 === # 项目结构: # tests/ # __init__.py # api/ # test_login.py # utils/ # test_helpers.py # 包含测试辅助函数 # 在test_login.py中: # from ..utils.test_helpers import validate_response # 相对导入辅助函数 # 实际函数实现: def validate_response(response, expected_status, schema=None): """验证API响应是否符合预期""" # 检查状态码 assert response.status_code == expected_status, \ f"预期状态码 {expected_status},实际 {response.status_code}" # 如果提供了JSON schema则验证 if schema: from jsonschema import validate # 延迟导入 validate(instance=response.json(), schema=schema) return True # ================== 第三部分:接口测试专用模块导入实践 ================== # === 示例7:requests库在接口测试中的完整应用 === import json # 导入JSON处理模块 import time # 导入时间模块 def test_login_api(): """测试登录接口(Windows环境适用)""" # 准备测试数据 payload = { "username": "testuser", "password": "Test123!" # 测试密码 } start_time = time.time() # 记录开始时间 try: # 发送POST请求 response = requests.post( url=f"{API_URL}/login", # 使用配置的API URL json=payload, # 请求体数据 timeout=5 # 超时设置(秒) ) duration = time.time() - start_time # 计算耗时 # 验证响应 assert response.status_code == 200, "登录失败" assert "access_token" in response.json(), "响应中缺少access_token" print(f"✅ 登录测试通过,耗时: {duration:.3f}秒") return { "test_case": "login_api", "status": "PASS", "duration": duration } except Exception as e: duration = time.time() - start_time print(f"❌ 登录测试失败: {str(e)}") return { "test_case": "login_api", "status": "FAIL", "error": str(e), "duration": duration } # === 示例8:pytest测试框架中的模块导入 === import pytest # 导入测试框架 from requests.exceptions import Timeout # 导入特定异常 @pytest.mark.parametrize("username,password", [ ("valid_user", "ValidPass123!"), ("", "password"), # 空用户名 ("user", "") # 空密码 ]) def test_login_validation(username, password): """参数化测试登录验证(Windows环境适用)""" response = requests.post( f"{API_URL}/login", json={"username": username, "password": password}, timeout=3 ) if username and password: assert response.status_code == 200 else: assert response.status_code == 400 # === 示例9:测试数据驱动的模块导入 === import csv # 导入CSV模块 def load_test_data(file_path): """从CSV加载测试数据(Windows环境适用)""" test_cases = [] with open(file_path, mode='r', encoding='utf-8') as file: reader = csv.DictReader(file) for row in reader: # 转换数据类型 row['expected_status'] = int(row['expected_status']) test_cases.append(row) print(f"✅ 已加载 {len(test_cases)} 条测试用例") return test_cases # ================== 第四部分:总结 - 测试中模块导入最佳实践 ================== """ ✅ 测试工程师模块导入最佳实践: 1. 导入顺序规范: import os # 1. 标准库 import requests # 2. 第三方测试库 from . import utils # 3. 本地测试模块 2. 测试专用导入技巧: - 对pytest、requests等高频模块使用完整导入 - 对辅助功能使用精准导入(from module import function) - 对长模块名使用别名(import pandas as pd) - 对资源密集型模块使用延迟导入 3. 接口测试核心模块: import requests # HTTP接口测试 import pytest # 测试框架 import json # 响应处理 import csv # 测试数据管理 import os # 文件/路径操作 🚫 测试中常见问题解决方案: 1. ModuleNotFoundError: - 创建requirements.txt包含测试依赖 - 使用虚拟环境隔离项目依赖 2. 循环导入问题: # 测试模块A导入模块B,同时B又导入A 解决方案: a. 重构代码,提取公共部分到新模块C b. 将导入移到函数内部 3. Windows路径问题: - 使用os.path.join()构建路径 - 使用pathlib模块进行现代路径处理 - 避免硬编码反斜杠(\) 4. 环境配置问题: - 使用dotenv管理环境变量 - 分离不同环境的配置文件 """ # === 综合示例:完整的接口测试工作流 === def run_api_test_suite(): """执行API测试套件(Windows环境适用)""" print("=" * 50) print("开始API测试套件") start_time = time.time() # 收集测试结果 test_results = [] # 测试登录接口 login_result = test_login_api() test_results.append(login_result) # 测试用户获取接口 user_result = test_user_api() test_results.append(user_result) # 创建测试报告 create_test_report(test_results) duration = time.time() - start_time print(f"测试完成! 总耗时: {duration:.2f}秒") print("=" * 50) def test_user_api(): """测试用户接口(Windows环境适用)""" print("执行用户接口测试...") start_time = time.time() try: response = requests.get(f"{API_URL}/users") assert response.status_code == 200 users = response.json() assert len(users) > 0, "用户列表为空" duration = time.time() - start_time print(f"✅ 获取到 {len(users)} 个用户") return { "test_case": "user_api", "status": "PASS", "duration": duration } except Timeout: duration = time.time() - start_time print("❌ 用户接口请求超时") return { "test_case": "user_api", "status": "FAIL", "error": "Timeout", "duration": duration } # 特殊语法解释: # if __name__ == "__main__": # 这个条件判断用于确定当前脚本是直接运行还是被导入到其他脚本中 # 当Python文件直接运行时,__name__ 的值被设置为 "__main__" # 当文件被导入为模块时,__name__ 的值是模块名 # 这样可以确保下面的代码只在直接运行此脚本时执行 if __name__ == "__main__": # 配置测试环境(模拟) os.environ["TEST_ENV"] = "test" # 当脚本被直接运行时执行测试套件 run_api_test_suite() 现在的课件不太好,优化下,格式如下:1.需要总结本课件会教学的内容2。需要解释什么是导入,3.需要分别讲解3种导入的方式并且给予例子,4.1. requests - HTTP接口测试 2. pytest - 测试框架 3. json/csv - 测试数据处理 4. logging - 测试日志记录 5. os/sys - 系统/环境操作 需要把这四种导入都讲清楚,文件处理可以不用讲,我单独拆开,5.最后再总结,要求注释足够详细,并且例子也足够多
最新发布
08-26
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值